Custom Functions

source("custom_functions.R")

2. Hypothesis: 2. PSC recurrence is associated with a specific composition of the gut microbiome

rPSC vs non-rPSC vs Healthy analysis on merged data

rPSC vs non-rPSC –by this comparison, we will find the effect of recurrence (whether the microbial composition is associated with it)

non-rPSC vs Healthy – by this comparison, we will find if the non-rPSC samples are „closer“ to the healthy samples then rPSC samples in terms of the microbial composition. In other words, does non-rPSC samples have „healthy microbiome“?

rPSC vs Healthy – by this comparison, we will find how much are the rPSC samples different from healthy samples.

However, the rPSC and non-rPSC samples are not different at all (see results). Therefore, we can do EXCLUSIVE LEFT JOIN of differentially abundant taxa from the analyses (rPSC vs Healthy, non-rPSC vs Healthy)

Data Import

Importing ASV, taxa and metadata tables for both czech and norway samples.

Data Import

Importing ASV, taxa and metadata tables for both Czech and Norway samples.

Czech

path = "../../data/analysis_ready_data/ikem/"
asv_tab_ikem <- as.data.frame(fread(file.path(path,"asv_table_ikem.csv"),
                                    check.names = FALSE))
taxa_tab_ikem <- as.data.frame(fread(file.path(path,"taxa_table_ikem.csv"),
                                     check.names = FALSE))
metadata_ikem <- as.data.frame(fread(file.path(path,"metadata_ikem.csv"),
                                     check.names = FALSE))

Norway

path = "../../data/analysis_ready_data/norway/"
asv_tab_norway <- as.data.frame(fread(file.path(path,"asv_table_norway.csv"),
                                    check.names = FALSE))
taxa_tab_norway <- as.data.frame(fread(file.path(path,"taxa_table_norway.csv"),
                                    check.names = FALSE))
metadata_norway <- as.data.frame(fread(file.path(path,"metadata_norway.csv"),
                                    check.names = FALSE))

Merging data

Merging two countries to create whole dataset

asv_tab <- merge(asv_tab_ikem,asv_tab_norway,by="SeqID",all=TRUE)
taxa_tab <- merging_taxa_tables(taxa_tab_ikem,taxa_tab_norway)
Merging at ASV level
Finding inconsistencies in taxonomy, trying to keep the ones that have better taxonomy assignment

Merging two countries based on the different matrices - Ileum, Colon.

Terminal ileum

ileum_data <- merging_data(asv_tab_1=asv_tab_ikem,
                           asv_tab_2=asv_tab_norway,
                           taxa_tab_1=taxa_tab_ikem,
                           taxa_tab_2=taxa_tab_norway,
                           metadata_1=metadata_ikem,
                           metadata_2=metadata_norway,
                           segment="TI",Q="Q2")
Removing 1498 ASV(s)
Removing 1834 ASV(s)
Merging at ASV level
Finding inconsistencies in taxonomy, trying to keep the ones that have better taxonomy assignment
Removing 641 ASV(s)
ileum_asv_tab <- ileum_data[[1]]
ileum_taxa_tab <- ileum_data[[2]]
ileum_metadata <- ileum_data[[3]]

Colon

colon_data <- merging_data(asv_tab_1=asv_tab_ikem,
                           asv_tab_2=asv_tab_norway,
                           taxa_tab_1=taxa_tab_ikem,
                           taxa_tab_2=taxa_tab_norway,
                           metadata_1=metadata_ikem,
                           metadata_2=metadata_norway,
                           segment="colon",Q="Q2")
Removing 739 ASV(s)
Removing 266 ASV(s)
Merging at ASV level
Finding inconsistencies in taxonomy, trying to keep the ones that have better taxonomy assignment
Removing 1096 ASV(s)
colon_asv_tab <- colon_data[[1]]
colon_taxa_tab <- colon_data[[2]]
colon_metadata <- colon_data[[3]]

Data Analysis - Terminal ileum

segment="terminal_ileum"

Filtering

Rules: - prevalence > 5% (per group) - nearZeroVar with default settings - sequencing depth > 5000 - taxonomic assignment at least order

Rarefaction Curve

path="../intermediate_files/rarecurves"
seq_depth_threshold <- 10000
ps <- construct_phyloseq(ileum_asv_tab,ileum_taxa_tab,ileum_metadata)
rareres <- get_rarecurve(obj=ps, chunks=500)
save(rareres,file = file.path(path,"rarefaction_ileum.Rdata"))
load(file.path(path,"rarefaction_ileum.Rdata"))

prare <- ggrarecurve(obj=rareres,
                      factorNames="Country",
                      indexNames=c("Observe")) + 
  theme_bw() +
  theme(axis.text=element_text(size=8), panel.grid=element_blank(),
        strip.background = element_rect(colour=NA,fill="grey"),
        strip.text.x = element_text(face="bold")) + 
  geom_vline(xintercept = seq_depth_threshold, 
             linetype="dashed", 
             color = "red") + 
  xlim(0, 20000)
Warning: NaNs producedThe color has been set automatically, you can reset it manually by adding scale_color_manual(values=yourcolors)
prare

Library size

read_counts(ileum_asv_tab, line = c(5000,10000))
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.

Sequencing depth

data_filt <- seq_depth_filtering(ileum_asv_tab,
                                 ileum_taxa_tab,
                                 ileum_metadata,
                                 seq_depth_threshold = 10000)
Removing 104 ASV(s)
filt_ileum_asv_tab <- data_filt[[1]]; alpha_ileum_asv_tab <- filt_ileum_asv_tab
filt_ileum_taxa_tab <- data_filt[[2]]; alpha_ileum_taxa_tab <- filt_ileum_taxa_tab
filt_ileum_metadata <- data_filt[[3]]; alpha_ileum_metadata <- filt_ileum_metadata

seq_step <- dim(filt_ileum_asv_tab)[1]

Library size

read_counts(filt_ileum_asv_tab,line = c(5000,10000))
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.

NearZeroVar

data_filt <- nearzerovar_filtering(filt_ileum_asv_tab, 
                                   filt_ileum_taxa_tab,
                                   filt_ileum_metadata)

filt_ileum_asv_tab <- data_filt[[1]]
filt_ileum_taxa_tab <- data_filt[[2]]
nearzero_step <- dim(filt_ileum_asv_tab)[1]

Library size

read_counts(filt_ileum_asv_tab,line = c(5000,10000))
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.

Final Counts

final_counts_filtering(ileum_asv_tab,
                       filt_ileum_asv_tab,
                       filt_ileum_metadata,
                       seq_step, 0, nearzero_step) %>% `colnames<-`("Count")

Alpha diversity

path = "../results/Q2/alpha_diversity"

Calculation

# Construct MPSE object
alpha_ileum_metadata$Sample <- alpha_ileum_metadata$SampleID
ileum_mpse <- as.MPSE(construct_phyloseq(alpha_ileum_asv_tab,
                                         alpha_ileum_taxa_tab,
                                         alpha_ileum_metadata))

ileum_mpse %<>% mp_rrarefy(raresize = 10000,seed = 123)

# Calculate alpha diversity - rarefied counts
ileum_mpse %<>% mp_cal_alpha(.abundance=RareAbundance, force=TRUE)

alpha_div_plots <- list()

# preparing data frame
alpha_data <- data.frame(SampleID=ileum_mpse$Sample.x,
                         Observe=ileum_mpse$Observe,
                         Shannon=ileum_mpse$Shannon,
                         Simpson=ileum_mpse$Simpson,
                         Pielou=ileum_mpse$Pielou,
                         Group=ileum_mpse$Group,
                         Country=ileum_mpse$Country,
                         Patient=ileum_mpse$Patient)

write.csv(alpha_data,file.path(path,paste0("alpha_indices_",segment,".csv")),
          row.names = FALSE)

Plots

Country plot

p_boxplot_alpha <- alpha_diversity_countries(alpha_data)
Using SampleID, Group, Country, Patient as id variables
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.Using SampleID, Group, Country, Patient as id variables
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.
# save the results
alpha_div_plots[[paste(segment,"Country")]] <- p_boxplot_alpha

# see the results
p_boxplot_alpha

pdf("../figures/Q2/alpha_diversity_terminal_ileum.pdf",
    height =4,width = 7)
p_boxplot_alpha
dev.off()

Custom plot

alpha_data <- alpha_data %>% 
  dplyr::select(-c("Simpson","Pielou")) %>%
  mutate(Richness=Observe)

p_A <- alpha_diversity_custom_2(alpha_data,
                                size = 1.5,
                                width = 0.3)
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.Scale for y is already present.
Adding another scale for y, which will replace the existing scale.
# save the results
alpha_div_plots[[paste(segment,"Custom")]] <- p_A

p_A

Linear Model

path = "../results/Q2/alpha_diversity"
alpha_data <- read.csv(file.path(path,paste0("alpha_indices_",segment,".csv")))

Richness

results_model <- pairwise.lm(formula = "Observe ~ Group * Country",
                             factors=alpha_data$Group,
                             data=alpha_data)

# check interaction
if (!is.data.frame(results_model)){
  results_model_observe <- results_model[[1]]
  results_model_observe_emeans <- results_model[[2]]
} else {
  results_model_observe <- results_model
  results_model_observe_emeans <- NA
}

# save the results
pc_observed <- list(); 
pc_observed[[segment]] <- results_model_observe
# see the results
knitr::kable(results_model_observe,digits = 3,
caption = "Raw results of linear model of richness estimation.")
Raw results of linear model of richness estimation.
Estimate Std..Error t.value Pr…t.. p.adj sig
non-rPSC vs GrouprPSC -12.199 11.972 -1.019 0.310 0.349
non-rPSC , rPSC - CZ vs NO -21.486 11.452 -1.876 0.063 0.141
non-rPSC vs GrouprPSC:CountryNO 9.347 23.088 0.405 0.686 0.686
healthy vs GrouprPSC -37.741 12.284 -3.072 0.003 0.025 *
healthy , rPSC - CZ vs NO 11.203 10.973 1.021 0.310 0.349
healthy vs GrouprPSC:CountryNO -23.342 21.355 -1.093 0.277 0.349
healthy vs Groupnon-rPSC -25.542 9.322 -2.740 0.007 0.031 *
healthy , non-rPSC - CZ vs NO 11.203 10.933 1.025 0.307 0.349
healthy vs Groupnon-rPSC:CountryNO -32.689 15.108 -2.164 0.032 0.096

knitr::kable(results_model_observe_emeans,digits = 3,
caption = "Raw results of independent country analysis")
Raw results of independent country analysis
contrast Country estimate SE df t.ratio p.value
(non-rPSC) - healthy CZ -25.542 9.322 174 -2.740 0.007
(non-rPSC) - healthy NO -58.231 11.889 174 -4.898 0.000

Shannon

results_model <- pairwise.lm(formula = "Shannon ~ Group * Country",
                             factors=alpha_data$Group,
                             data=alpha_data)

# check interaction
if (!is.data.frame(results_model)){
  results_model_shannon <- results_model[[1]]
  results_model_shannon_emeans <- results_model[[2]]
} else {
  results_model_shannon <- results_model
  results_model_shannon_emeans <- NA
}

# save the results
pc_shannon <- list(); 
pc_shannon[[segment]] <- as.data.frame(results_model_shannon)
# see the results
knitr::kable(results_model_shannon,digits = 3,
caption = "Raw results of linear model of Shannon estimation.")
Raw results of linear model of Shannon estimation.
Estimate Std..Error t.value Pr…t.. p.adj sig
non-rPSC vs GrouprPSC -0.102 0.146 -0.696 0.487 0.731
non-rPSC , rPSC - CZ vs NO -0.349 0.140 -2.500 0.014 0.123
non-rPSC vs GrouprPSC:CountryNO -0.006 0.281 -0.021 0.983 0.983
healthy vs GrouprPSC -0.210 0.140 -1.501 0.137 0.321
healthy , rPSC - CZ vs NO 0.005 0.125 0.043 0.966 0.983
healthy vs GrouprPSC:CountryNO -0.360 0.244 -1.478 0.142 0.321
healthy vs Groupnon-rPSC -0.109 0.115 -0.948 0.344 0.620
healthy , non-rPSC - CZ vs NO 0.005 0.135 0.040 0.968 0.983
healthy vs Groupnon-rPSC:CountryNO -0.354 0.186 -1.905 0.058 0.263

knitr::kable(results_model_shannon_emeans,digits = 3,
caption = "Raw results of independent country analysis")
Raw results of independent country analysis
contrast Country estimate SE df t.ratio p.value
(non-rPSC) - healthy CZ -0.109 0.115 174 -0.948 0.344
(non-rPSC) - healthy NO -0.463 0.146 174 -3.164 0.002

Simpson

results_model <- pairwise.lm(formula = "Simpson ~ Group * Country",
                                     factors=alpha_data$Group,
                                     data=alpha_data)

# check interaction
if (!is.data.frame(results_model)){
  results_model_simpson <- results_model[[1]]
  results_model_simpson_emeans <- results_model[[2]]
} else {
  results_model_simpson <- results_model
  results_model_simpson_emeans <- NA
}


# save the results
pc_simpson <- list(); 
pc_simpson[[segment]] <- as.data.frame(results_model_simpson)
# see the results
knitr::kable(results_model_simpson,digits = 3,
caption = "Raw results of linear model of Simpson estimation.")
Raw results of linear model of Simpson estimation.
Estimate Std..Error t.value Pr…t.. p.adj sig
non-rPSC vs GrouprPSC 0.000 0.023 0.019 0.985 0.985
non-rPSC , rPSC - CZ vs NO -0.034 0.022 -1.573 0.118 0.531
non-rPSC vs GrouprPSC:CountryNO -0.029 0.043 -0.661 0.510 0.767
healthy vs GrouprPSC -0.009 0.018 -0.500 0.618 0.767
healthy , rPSC - CZ vs NO -0.008 0.016 -0.501 0.617 0.767
healthy vs GrouprPSC:CountryNO -0.055 0.031 -1.779 0.078 0.531
healthy vs Groupnon-rPSC -0.009 0.016 -0.564 0.574 0.767
healthy , non-rPSC - CZ vs NO -0.008 0.019 -0.410 0.682 0.767
healthy vs Groupnon-rPSC:CountryNO -0.026 0.027 -0.975 0.331 0.767

knitr::kable(results_model_simpson_emeans,digits = 3,
caption = "Raw results of independent country analysis")
Raw results of independent country analysis
contrast Country estimate SE df t.ratio p.value
rPSC - healthy CZ -0.009 0.018 102 -0.500 0.618
rPSC - healthy NO -0.064 0.025 102 -2.526 0.013

Pielou

results_model <- pairwise.lm(formula = "Pielou ~ Group * Country",
                                     factors=alpha_data$Group,
                                     data=alpha_data)

# check interaction

if (!is.data.frame(results_model)){
  results_model_pielou <- results_model[[1]]
  results_model_pielou_emeans <- results_model[[2]]
} else {
  results_model_pielou <- results_model
  results_model_pielou_emeans <- NA
}

# save the results
pc_pielou <- list(); 
pc_pielou[[segment]] <- as.data.frame(results_model_pielou)
# see the results
knitr::kable(results_model_pielou,digits = 3,
caption = "Raw results of linear model of Pielou estimation.")
Raw results of linear model of Pielou estimation.
Estimate Std..Error t.value Pr…t.. p.adj sig
non-rPSC vs GrouprPSC -0.004 0.022 -0.184 0.854 0.946
non-rPSC , rPSC - CZ vs NO -0.047 0.021 -2.260 0.025 0.229
non-rPSC vs GrouprPSC:CountryNO -0.005 0.042 -0.108 0.914 0.946
healthy vs GrouprPSC -0.001 0.021 -0.067 0.946 0.946
healthy , rPSC - CZ vs NO -0.009 0.018 -0.463 0.645 0.946
healthy vs GrouprPSC:CountryNO -0.043 0.036 -1.195 0.235 0.705
healthy vs Groupnon-rPSC 0.003 0.018 0.146 0.884 0.946
healthy , non-rPSC - CZ vs NO -0.009 0.021 -0.409 0.683 0.946
healthy vs Groupnon-rPSC:CountryNO -0.038 0.029 -1.329 0.185 0.705

knitr::kable(results_model_pielou_emeans,digits = 3,
caption = "Raw results of independent country analysis")

Table: Raw results of independent country analysis

Saving results

alpha_list <- list(
  Richness=pc_observed[[segment]] %>% rownames_to_column("Comparison"),
  Shannon=pc_shannon[[segment]] %>% rownames_to_column("Comparison"),
  Simpson=pc_simpson[[segment]] %>% rownames_to_column("Comparison"),
  Pielou=pc_pielou[[segment]] %>% rownames_to_column("Comparison"))
                   
write.xlsx(alpha_list, 
           file = file.path(path,paste0("alpha_diversity_results_",segment,".xlsx")))

Beta diversity

Calculating Aitchison distance (euclidean distance on clr-transformed data), both at ASV and genus level.

Main analysis - Genus, Aitchison

Genus level, Aitchison distance

level="genus"
path = "../results/Q2/beta_diversity"
pairwise_aitchison_raw <- list()
pca_plots_list <- list()

Aggregation, filtering

# Aggregation
genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level=level,
                             names=TRUE)
# Filtration
filt_data <- filtering_steps(genus_data[[1]],
                             genus_data[[2]],
                             ileum_metadata,
                             seq_depth_threshold=10000)
Removing 2 ASV(s)
filt_ileum_genus_tab <- filt_data[[1]]
filt_ileum_genus_taxa <- filt_data[[2]]
filt_ileum_metadata <- filt_data[[3]]
PERMANOVA
pairwise_df <- filt_ileum_genus_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,
                           filt_ileum_metadata$Group,
                           covariate = filt_ileum_metadata$Country, sim.method = "robust.aitchison", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, interaction = TRUE, sim.method = "robust.aitchison", p.adjust.m="BH")

# tidy the results
pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
pairwise_aitchison_raw[[paste(level, segment)]] <- rbind(pp_factor,pp_cov,pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 215.579 1.208 0.009 0.107 0.107
rPSC vs healthy 1 561.696 3.345 0.030 0.001 0.002 **
non-rPSC vs healthy 1 760.242 4.431 0.024 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 601.929 3.372 0.024 0.001 0.001 ***
rPSC vs healthy , Country 1 496.841 2.959 0.027 0.001 0.001 ***
non-rPSC vs healthy , Country 1 624.474 3.640 0.020 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 156.176 0.874 0.006 0.788 0.788
rPSC vs healthy : Country 1 164.743 0.981 0.009 0.464 0.696
non-rPSC vs healthy : Country 1 209.954 1.225 0.007 0.089 0.267

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

if (length(interaction_sig)>0){
  for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_ileum_metadata$Group,
                      covariate = filt_ileum_metadata$Country, 
                      group1 = group1,
                      group2 = group2)
  print(result_list)
}
}
Plots

Custom

p <- pca_plot_custom(filt_ileum_genus_tab,
                                 filt_ileum_genus_taxa,
                                 filt_ileum_metadata,
                                 show_boxplots = TRUE,
                                 variable = "Group", size=3, show_legend=FALSE)

# save the results
pca_plots_list[[paste(segment,level,"custom")]] <- p

# see the results
p

pdf("../figures/Q2/beta_diversity_terminal_ileum.pdf",
    height =5,width = 5)
p
dev.off()

Saving results

write.xlsx(pairwise_aitchison_raw[[paste(level, segment)]], 
           file = file.path(path,
           paste0("beta_diversity_results_", segment,".xlsx")))

Supplementary analysis

supplements_beta <- list()

Genus level

level="genus"
Bray-Curtis

PERMANOVA

pairwise_df <- filt_ileum_genus_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, sim.method = "bray", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, interaction = TRUE, sim.method = "bray", p.adjust.m="BH")

# tidy the results
pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("bray",level,segment)]] <- rbind(pp_factor,pp_cov,pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.251 1.208 0.008 0.241 0.241
rPSC vs healthy 1 0.813 4.432 0.039 0.001 0.002 **
non-rPSC vs healthy 1 1.241 6.538 0.034 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 1.449 6.976 0.049 0.001 0.001 ***
rPSC vs healthy , Country 1 0.972 5.300 0.047 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.336 7.038 0.037 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 0.151 0.724 0.005 0.803 0.803
rPSC vs healthy : Country 1 0.287 1.572 0.014 0.067 0.100
non-rPSC vs healthy : Country 1 0.354 1.873 0.010 0.011 0.033 *

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_ileum_metadata$Group,
                      covariate = filt_ileum_metadata$Country, 
                      group1 = group1,
                      group2 = group2,
                      sim.method = 'bray')
  print(result_list)
}
$`non-rPSC_healthy_CZ`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1   0.5823 0.02622 3.0424  0.001      0.001
Residual 113  21.6268 0.97378                         
Total    114  22.2090 1.00000                         

$`non-rPSC_healthy_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
         Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac       1   1.0126 0.08265 5.4958  0.001      0.001
Residual 61  11.2391 0.91735                         
Total    62  12.2517 1.00000                         

$`non-rPSC_CZ_vs_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov        1   1.0157 0.04597 4.9629  0.001      0.001
Residual 103  21.0797 0.95403                         
Total    104  22.0954 1.00000                         

$healthy_CZ_vs_NO
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
         Df SumOfSqs     R2      F Pr(>F) p.adjusted
Cov       1   0.6741 0.0541 4.0607  0.001      0.001
Residual 71  11.7862 0.9459                         
Total    72  12.4603 1.0000                         

Plots

p <- pca_plot_custom(filt_ileum_genus_tab,
                                 filt_ileum_genus_taxa,
                                 filt_ileum_metadata,
                                 measure = "bray",
                                 show_boxplots = TRUE,
                                 variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA bray",level,segment)]] <- p

# see the results
p

Jaccard

PERMANOVA

pairwise_df <- filt_ileum_genus_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, sim.method = "jaccard", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, interaction = TRUE, sim.method = "jaccard", p.adjust.m="BH")

# tidy the results
pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("jaccard",level,segment)]] <- rbind(pp_factor, 
                                                            pp_cov, 
                                                            pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.337 1.138 0.008 0.241 0.241
rPSC vs healthy 1 0.887 3.269 0.030 0.001 0.002 **
non-rPSC vs healthy 1 1.349 4.846 0.026 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 1.460 4.927 0.035 0.001 0.001 ***
rPSC vs healthy , Country 1 1.092 4.023 0.036 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.476 5.300 0.029 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 0.242 0.817 0.006 0.823 0.823
rPSC vs healthy : Country 1 0.342 1.261 0.011 0.118 0.177
non-rPSC vs healthy : Country 1 0.445 1.604 0.009 0.014 0.042 *

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_ileum_metadata$Group,
                      covariate = filt_ileum_metadata$Country, 
                      group1 = group1,
                      group2 = group2,
                      sim.method = 'jaccard')
  print(result_list)
}
$`non-rPSC_healthy_CZ`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1    0.699 0.02174 2.5112  0.001      0.001
Residual 113   31.468 0.97826                         
Total    114   32.167 1.00000                         

$`non-rPSC_healthy_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
         Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac       1   1.0948 0.06116 3.9739  0.001      0.001
Residual 61  16.8056 0.93884                         
Total    62  17.9004 1.00000                         

$`non-rPSC_CZ_vs_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov        1   1.0948 0.03497 3.7326  0.001      0.001
Residual 103  30.2119 0.96503                         
Total    104  31.3067 1.00000                         

$healthy_CZ_vs_NO
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: free
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
         Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov       1   0.8258 0.04372 3.2463  0.001      0.001
Residual 71  18.0612 0.95628                         
Total    72  18.8870 1.00000                         

Plots

Custom

p <- pca_plot_custom(filt_ileum_genus_tab,
                                 filt_ileum_genus_taxa,
                                 filt_ileum_metadata,
                                 measure = "jaccard",
                                 show_boxplots = TRUE,
                                 variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA jaccard",level,segment)]] <- p

# see the results
p

ASV level

level="ASV"
Aitchison

PERMANOVA

# preparing data frame
pairwise_df <- filt_ileum_asv_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, sim.method = "robust.aitchison", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, interaction = TRUE, sim.method = "robust.aitchison", p.adjust.m="BH")

pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("aitchison",level,segment)]] <- rbind(pp_factor, 
                                                            pp_cov, 
                                                            pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 316.296 1.176 0.008 0.071 0.071
rPSC vs healthy 1 830.867 2.897 0.027 0.001 0.002 **
non-rPSC vs healthy 1 1156.137 4.137 0.023 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 639.519 2.378 0.017 0.001 0.001 ***
rPSC vs healthy , Country 1 598.496 2.087 0.019 0.001 0.001 ***
non-rPSC vs healthy , Country 1 752.840 2.694 0.015 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 222.179 0.825 0.006 0.960 0.96
rPSC vs healthy : Country 1 262.783 0.916 0.008 0.746 0.96
non-rPSC vs healthy : Country 1 291.928 1.045 0.006 0.333 0.96

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

if (length(interaction_sig)>0){
for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_ileum_metadata$Group,
                      covariate = filt_ileum_metadata$Country, 
                      group1 = group1,
                      group2 = group2)
  print(result_list)
}
}

PCoA

p <- pca_plot_custom(filt_ileum_asv_tab,
                           filt_ileum_taxa_tab,
                           filt_ileum_metadata,
                           show_boxplots = TRUE,
                           variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA aitchison",level,segment)]] <- p

# see the results
p

Bray-Curtis

PERMANOVA

# preparing data frame
pairwise_df <- filt_ileum_asv_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, sim.method = "bray", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, interaction = TRUE, sim.method = "bray", p.adjust.m="BH")

pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("bray",level,segment)]] <- rbind(pp_factor, 
                                                            pp_cov, 
                                                            pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.505 1.557 0.011 0.026 0.026 *
rPSC vs healthy 1 1.342 4.364 0.039 0.001 0.002 **
non-rPSC vs healthy 1 1.979 6.424 0.034 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 1.444 4.451 0.032 0.001 0.001 ***
rPSC vs healthy , Country 1 1.059 3.444 0.031 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.394 4.525 0.024 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 0.333 1.027 0.007 0.386 0.386
rPSC vs healthy : Country 1 0.390 1.272 0.011 0.093 0.140
non-rPSC vs healthy : Country 1 0.447 1.456 0.008 0.036 0.108

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

if (length(interaction_sig)>0){
for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_ileum_metadata$Group,
                      covariate = filt_ileum_metadata$Country, 
                      group1 = group1,
                      group2 = group2,
                      sim.method = 'bray')
  print(result_list)
}
}

PCoA

p <- pca_plot_custom(filt_ileum_asv_tab,
                     filt_ileum_taxa_tab,
                     filt_ileum_metadata,
                     measure = "bray",
                     show_boxplots = TRUE,
                     variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA bray",level,segment)]] <- p

# see the results
p

Jaccard

PERMANOVA

# preparing data frame
pairwise_df <- filt_ileum_asv_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, sim.method = "jaccard", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,filt_ileum_metadata$Group,covariate = filt_ileum_metadata$Country, interaction = TRUE, sim.method = "jaccard", p.adjust.m="BH")

pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("jaccard",level,segment)]] <- rbind(pp_factor, 
                                                            pp_cov, 
                                                            pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.518 1.318 0.009 0.029 0.029 *
rPSC vs healthy 1 1.117 2.934 0.027 0.001 0.002 **
non-rPSC vs healthy 1 1.607 4.216 0.023 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 1.214 3.089 0.022 0.001 0.001 ***
rPSC vs healthy , Country 1 0.939 2.467 0.023 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.203 3.157 0.017 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 0.390 0.992 0.007 0.469 0.469
rPSC vs healthy : Country 1 0.430 1.130 0.010 0.131 0.196
non-rPSC vs healthy : Country 1 0.501 1.318 0.007 0.026 0.078

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

if (length(interaction_sig)>0){
for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_ileum_metadata$Group,
                      covariate = filt_ileum_metadata$Country, 
                      group1 = group1,
                      group2 = group2,
                      sim.method = 'jaccard')
  print(result_list)
}
}

PCoA

p <- pca_plot_custom(filt_ileum_asv_tab,
                     filt_ileum_taxa_tab,
                     filt_ileum_metadata,
                     measure = "jaccard",
                     show_boxplots = TRUE,
                     variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA jaccard",level,segment)]] <- p

# see the results
p

Saving results

write.xlsx(supplements_beta[!grepl("PCoA",names(supplements_beta))],
           file = file.path(path,
           paste0("supplements_beta_diversity_", segment,".xlsx")))

Univariate Analysis

Main - Genus level

level="genus"
# needed paths
path = "../results/Q2/univariate_analysis"
path_maaslin=file.path("../intermediate_files/maaslin/Q2",level)
# variables
raw_linda_results_genus <- list();
raw_linda_results_genus[[segment]] <- list()
linda_results_genus <- list(); 
linda_results_genus[[segment]] <- list()

# country and interaction problems
list_country_union <- list()
list_intersections <- list()
list_venns <- list()
uni_statistics <- list()

# workbook for final df
wb <- createWorkbook()

# rPSC effect
rpsc_effect <- list()

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]

ileum_genus_asv_taxa_tab <- create_asv_taxa_table(ileum_genus_tab,
                                                  ileum_genus_taxa_tab)

rPSC vs non-rPSC

group <- c("non-rPSC","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
linDA

# prepare the data
linda_data <- binomial_prep(ileum_genus_tab,
                            ileum_genus_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")
Removing 55 ASV(s)
Removing 2 ASV(s)
filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  138  samples and  197  features will be tested!
Warning: Some features have less than 3 nonzero values! 
                        They have virtually no statistical power. You may consider filtering them in the analysis!
Imputation approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results_genus[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results_genus[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)
MaAsLin2
volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
Warning: Removed 1 row containing missing values or values outside the scale
range (`geom_text_repel()`).Warning: Removed 7 rows containing missing values or values outside the scale
range (`geom_text_repel()`).
volcano

Group - Intersection
intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_genus, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union
list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)
Interaction effect
list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)
Basic statistics
uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_genus[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "non-rPSC"
[1] "rPSC"
[1] "non-rPSC"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- comparison_name
addWorksheet(wb, sheetName = new_name)
writeData(wb, sheet = new_name, uni_df, rowNames=FALSE)

rPSC vs healthy

group <- c("healthy","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
linDA

# prepare the data
linda_data <- binomial_prep(ileum_genus_tab,
                            ileum_genus_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")
Removing 67 ASV(s)
Removing 4 ASV(s)
filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  106  samples and  207  features will be tested!
Imputation approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results_genus[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results_genus[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}

# summary statistics
# raw_linda_results_genus <- binomial_statistics(filt_ileum_uni_data,             
#                                             group=group,
#                                             filt_ileum_uni_metadata,
#                                             raw_linda_results_genus,
#                                             segment = "terminal_ileum")
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)
MaAsLin2
volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
Warning: Removed 23 rows containing missing values or values outside the scale
range (`geom_text_repel()`).Warning: Removed 9 rows containing missing values or values outside the scale
range (`geom_text_repel()`).
volcano

Group - Intersection
intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_genus, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union
list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)
Interaction effect
list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)
Basic statistics
uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_genus[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "rPSC"
[1] "healthy"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- comparison_name
addWorksheet(wb, sheetName = new_name)
writeData(wb, sheet = new_name, uni_df, rowNames=FALSE)

non-rPSC vs healthy

group <- c("healthy","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
linDA

# prepare the data
linda_data <- binomial_prep(ileum_genus_tab,
                            ileum_genus_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")
Removing 24 ASV(s)
Removing 2 ASV(s)
filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  178  samples and  179  features will be tested!
Imputation approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results_genus[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results_genus[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}

# summary statistics
# raw_linda_results_genus <- binomial_statistics(filt_ileum_uni_data,             
#                                             group=group,
#                                             filt_ileum_uni_metadata,
#                                             raw_linda_results_genus,
#                                             segment = "terminal_ileum")
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)
MaAsLin2
volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
Warning: Removed 32 rows containing missing values or values outside the scale
range (`geom_text_repel()`).Warning: Removed 14 rows containing missing values or values outside the scale
range (`geom_text_repel()`).
volcano

Group - Intersection
intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_genus, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union
list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)
Interaction effect
list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)
Basic statistics
uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_genus[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "non-rPSC"
[1] "healthy"
[1] "non-rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- comparison_name
addWorksheet(wb, sheetName = new_name)
writeData(wb, sheet = new_name, uni_df, rowNames=FALSE)

Visualization

Heatmap visualizing the linDA’s logFoldChange for taxa with p < 0.1.

list_heatmap <- list_intersections[grep(paste(segment,level),
                                  names(list_intersections),value=TRUE)]

p_heatmap_linda <- heatmap_linda(list_heatmap,ileum_taxa_tab)
p_heatmap_linda

Dot heatmap

dotheatmap_linda <- dot_heatmap_linda(
  list_heatmap,                               uni_statistics$terminal_ileum[grepl(level,names(uni_statistics$terminal_ileum))],
                                      ileum_taxa_tab) + xlab("") + ylab("")
min_clr -1.727234 
max_clr 7.029952 
min_log -4.215042 
max_log 3.331439 
dotheatmap_linda

Horizontal bar plot

p_prevalence <- horizontal_barplot(wb,taxa=levels(dotheatmap_linda$data$SeqID))
Using SeqID as id variables
p_prevalence_final <- ggarrange(p_prevalence,
                                ggplot() + theme_minimal(),
                                nrow = 2,heights = c(1,0.085))
p <- ggarrange(dotheatmap_linda + theme(legend.position = "none"),p_prevalence_final,ncol=2,widths = c(1,0.3))
Warning: Removed 64 rows containing missing values or values outside the scale
range (`geom_point()`).Warning: Removed 64 rows containing missing values or values outside the scale
range (`geom_text()`).
p


dot_heatmap_ileum <- p
pdf("../figures/Q2/dotplot_terminal_ileum.pdf",
    height =10,width = 4)
p
dev.off()

rPSC effect

pre_LTx vs Healthy and Post_LTx vs Healthy intersection

A <- list_intersections[[paste(segment,level,"healthy vs rPSC")]]
B <- list_intersections[[paste(segment,level,"healthy vs non-rPSC")]]
df <- A[!(A$SeqID %in% B$SeqID),]


rpsc_effect[[paste(segment,level)]] <- df
  
# see the results
rpsc_effect[[paste(segment,level)]] 

Saving results

# ALL DATA
saveWorkbook(wb,file.path(path,paste0("uni_analysis_wb_",segment,".xlsx")),
             overwrite = TRUE)

# PSC effect
write.xlsx(rpsc_effect[[paste(segment,level)]],file.path(path,paste0("rpsc_effect_",segment,".xlsx")))

# SIGNIFICANT taxa

write.xlsx(list_intersections[grepl(segment,names(list_intersections))] %>%
            `names<-`(gsub(segment, "", names(
              list_intersections[grepl(segment,names(list_intersections))]))),
           file.path(path,paste0("significant_taxa_",segment,".xlsx")))

Supplementary Analysis

supplements_uni <- list()
supplements_wb <- createWorkbook()

ASV level

level="ASV"
path_maaslin="../intermediate_files/maaslin/Q2/ASV/"
raw_linda_results <- list();
raw_linda_results[[segment]] <- list()
linda_results <- list(); 
linda_results[[segment]] <- list()
rPSC vs non-rPSC
group <- c("non-rPSC","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(ileum_asv_tab,
                            ileum_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")
Removing 1127 ASV(s)
Removing 27 ASV(s)
filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  138  samples and  466  features will be tested!
Warning: Some features have less than 3 nonzero values! 
                        They have virtually no statistical power. You may consider filtering them in the analysis!
Imputation approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "non-rPSC"
[1] "rPSC"
[1] "non-rPSC"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
rPSC vs healthy
group <- c("healthy","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(ileum_asv_tab,
                            ileum_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")
Removing 1214 ASV(s)
Removing 122 ASV(s)
filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  106  samples and  554  features will be tested!
Warning: Some features have less than 3 nonzero values! 
                        They have virtually no statistical power. You may consider filtering them in the analysis!
Pseudo-count approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}

# summary statistics
# raw_linda_results_genus <- binomial_statistics(filt_ileum_uni_data,             
#                                             group=group,
#                                             filt_ileum_uni_metadata,
#                                             raw_linda_results_genus,
#                                             segment = "terminal_ileum")
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "rPSC"
[1] "healthy"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
non-rPSC vs healthy
group <- c("healthy","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(ileum_asv_tab,
                            ileum_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")
Removing 392 ASV(s)
Removing 91 ASV(s)
filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  178  samples and  460  features will be tested!
Pseudo-count approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}

# summary statistics
# raw_linda_results_genus <- binomial_statistics(filt_ileum_uni_data,             
#                                             group=group,
#                                             filt_ileum_uni_metadata,
#                                             raw_linda_results_genus,
#                                             segment = "terminal_ileum")
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "non-rPSC"
[1] "healthy"
[1] "non-rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
Visualization

Heatmap visualizing the linDA’s logFoldChange for taxa with p < 0.1.

list_heatmap <- list_intersections[grep(paste(segment,level),
                                  names(list_intersections),value=TRUE)]

p_heatmap_linda <- heatmap_linda(list_heatmap,ileum_taxa_tab)
p_heatmap_linda

Dot heatmap

dotheatmap_linda <- dot_heatmap_linda(list_heatmap,
                                      uni_statistics$terminal_ileum[grepl(level,names(uni_statistics$terminal_ileum))],
                                      ileum_taxa_tab)
min_clr -0.9733804 
max_clr 4.946497 
min_log -4.9062 
max_log 5.67034 
dotheatmap_linda

rPSC effect

pre_LTx vs Healthy and Post_LTx vs Healthy intersection

A <- list_intersections[[paste(segment,level,"healthy vs rPSC")]]
B <- list_intersections[[paste(segment,level,"healthy vs non-rPSC")]]
df <- A[!(A$SeqID %in% B$SeqID),]


rpsc_effect[[paste(segment,level)]] <- df
  
# see the results
rpsc_effect[[paste(segment,level)]] 

Phylum level

level="phylum"
path_maaslin="../intermediate_files/maaslin/Q2/Phylum/"
raw_linda_results_phylum <- list();
raw_linda_results_phylum[[segment]] <- list()
linda_results_phylum <- list(); 
linda_results_phylum[[segment]] <- list()

Aggregate taxa

phylum_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = "Phylum")

ileum_phylum_tab <- phylum_data[[1]]
ileum_phylum_taxa_tab <- phylum_data[[2]]
rPSC vs non-rPSC
group <- c("non-rPSC","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(ileum_phylum_tab,
                            ileum_phylum_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")
Removing 3 ASV(s)
filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  138  samples and  11  features will be tested!
Imputation approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results_phylum[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results_phylum[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)
Using Phylum for naming
volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 
Using Phylum for naming
volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")
Using Phylum for naming
volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_phylum, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_phylum[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "non-rPSC"
[1] "rPSC"
[1] "non-rPSC"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
rPSC vs healthy
group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(ileum_phylum_tab,
                            ileum_phylum_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")
Removing 2 ASV(s)
filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  106  samples and  11  features will be tested!
Imputation approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results_phylum[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results_phylum[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}

# summary statistics
# raw_linda_results_genus <- binomial_statistics(filt_ileum_uni_data,             
#                                             group=group,
#                                             filt_ileum_uni_metadata,
#                                             raw_linda_results_genus,
#                                             segment = "terminal_ileum")
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)
Using Phylum for naming
volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 
Using Phylum for naming
volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")
Using Phylum for naming
volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)
volcano

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_phylum, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_phylum[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "rPSC"
[1] "healthy"
[1] "rPSC"
[1] "healthy"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
non-rPSC vs healthy
group <- c("healthy","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(ileum_phylum_tab,
                            ileum_phylum_taxa_tab,
                            ileum_metadata,
                            group, usage="linDA")

filt_ileum_uni_data <- linda_data[[1]]
filt_ileum_uni_taxa <- linda_data[[2]]
filt_ileum_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_ileum_uni_data, 
                   filt_ileum_uni_metadata, 
                   formula = '~ Group * Country')
0  features are filtered!
The filtered data has  178  samples and  10  features will be tested!
Imputation approach is used.
Fit linear models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results_phylum[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_ileum_uni_data,
                filt_ileum_uni_taxa)
  
  linda_results_phylum[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_ileum_uni_data,
             filt_ileum_uni_taxa)
}

# summary statistics
# raw_linda_results_genus <- binomial_statistics(filt_ileum_uni_data,             
#                                             group=group,
#                                             filt_ileum_uni_metadata,
#                                             raw_linda_results_genus,
#                                             segment = "terminal_ileum")
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, 
                                group1, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)
Using Phylum for naming
volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_ileum_uni_taxa) + 
            ggtitle("Country effect") 
Using Phylum for naming
volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_ileum_uni_taxa) +
            ggtitle("Interaction")
Using Phylum for naming
volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa) + 
            ggtitle(comparison_name)

volcano2 <- volcano_plot_maaslin(fit_data,filt_ileum_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_phylum, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_ileum_uni_data,
                                          filt_ileum_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_phylum[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "non-rPSC"
[1] "healthy"
[1] "non-rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
Visualization

Heatmap visualizing the linDA’s logFoldChange for taxa with p < 0.1.

list_heatmap <- list_intersections[grep(paste(segment,level),
                                  names(list_intersections),value=TRUE)]

p_heatmap_linda <- heatmap_linda(list_heatmap,ileum_taxa_tab)
p_heatmap_linda

Dot heatmap

dotheatmap_linda <- dot_heatmap_linda(list_heatmap,
                                      uni_statistics$terminal_ileum[grepl(level,names(uni_statistics$terminal_ileum))],
                                      ileum_taxa_tab)
min_clr -4.182065 
max_clr 4.949748 
min_log -2.332431 
max_log 2.832391 
dotheatmap_linda

rPSC effect

pre_LTx vs Healthy and Post_LTx vs Healthy intersection

A <- list_intersections[[paste(segment,level,"healthy vs rPSC")]]
B <- list_intersections[[paste(segment,level,"healthy vs non-rPSC")]]
df <- A[!(A$SeqID %in% B$SeqID),]

rpsc_effect[[paste(segment,level)]] <- df
  
# see the results
rpsc_effect[[paste(segment,level)]] 
NULL

Saving results

# ALL DATA
saveWorkbook(supplements_wb,file.path(path,paste0("supplements_uni_analysis_wb_",segment,".xlsx")),overwrite = TRUE)

# PSC effect
write.xlsx(rpsc_effect,
          file.path(path,paste0("supplements_rpsc_effect_",segment,".xlsx")))

# SIGNIFICANT taxa
write.xlsx(list_intersections[grepl(segment,names(list_intersections))] %>%
            `names<-`(gsub(segment, "", names(
              list_intersections[grepl(segment,names(list_intersections))]))),
           file.path(path,paste0("supplements_significant_taxa_",segment,".xlsx")))

Machine learning

path = "../results/Q2/models"

ElasticNet

model="enet"

ASV level

level="ASV"
rPSC vs non-rPSC
group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ <- list()
models_cm <- list()
betas <- list()
roc_cs <- list()

models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.3123848
auc                             0.5000000
auc_czech                       0.5000000
auc_no                          0.5000000
auc_optimism_corrected          0.5929044
auc_optimism_corrected_CIL      0.4774822
auc_optimism_corrected_CIU      0.6968581
accuracy                        0.7608696
accuracy_czech                        NaN
accuracy_no                     0.7500000
accuracy_optimism_corrected     0.7325629
accuracy_optimism_corrected_CIL 0.6374152
accuracy_optimism_corrected_CIU 0.8114948
enet_model$conf_matrices
$original
    0  
0 105 0
1  33 0

$czech
   0  
0 78 0
1 24 0

$no
   0  
0 27 0
1  9 0
enet_model$plot

roc_c

rPSC vs healthy
group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 1214 ASV(s)
Removing 122 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.2000000
lambda                          0.1112858
auc                             1.0000000
auc_czech                       1.0000000
auc_no                          1.0000000
auc_optimism_corrected          0.9566799
auc_optimism_corrected_CIL      0.8962456
auc_optimism_corrected_CIU      0.9859752
accuracy                        1.0000000
accuracy_czech                        NaN
accuracy_no                     1.0000000
accuracy_optimism_corrected     0.8766248
accuracy_optimism_corrected_CIL 0.7993421
accuracy_optimism_corrected_CIU 0.9369643
enet_model$conf_matrices
$original
    Predicted
True  0  1
   0 73  0
   1  0 33

$czech
    Predicted
True  0  1
   0 37  0
   1  0 24

$no
    Predicted
True  0  1
   0 36  0
   1  0  9
enet_model$plot


roc_c

non-rPSC vs healthy
group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 392 ASV(s)
Removing 91 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.2000000
lambda                          0.0310618
auc                             1.0000000
auc_czech                       1.0000000
auc_no                          1.0000000
auc_optimism_corrected          0.9355688
auc_optimism_corrected_CIL      0.8641787
auc_optimism_corrected_CIU      0.9782348
accuracy                        1.0000000
accuracy_czech                        NaN
accuracy_no                     1.0000000
accuracy_optimism_corrected     0.8680780
accuracy_optimism_corrected_CIL 0.7842294
accuracy_optimism_corrected_CIU 0.9209600
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0  73   0
   1   0 105

$czech
    Predicted
True  0  1
   0 37  0
   1  0 78

$no
    Predicted
True  0  1
   0 36  0
   1  0 27
enet_model$plot


roc_c

rPSC effect
model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_asv_tab,
                                                ileum_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.2737528
auc                             0.6350649
auc_czech                       0.6089744
auc_no                          0.7037037
auc_optimism_corrected          0.6554041
auc_optimism_corrected_CIL      0.5197632
auc_optimism_corrected_CIU      0.7667220
accuracy                        0.7608696
accuracy_czech                        NaN
accuracy_no                     0.7500000
accuracy_optimism_corrected     0.7583172
accuracy_optimism_corrected_CIL 0.6754902
accuracy_optimism_corrected_CIU 0.8096875
enet_model$conf_matrices
$original
    0  
0 105 0
1  33 0

$czech
   0  
0 78 0
1 24 0

$no
   0  
0 27 0
1  9 0
enet_model$plot


roc_c

Genus level

level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]
rPSC vs non-rPSC
group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.3119645
auc                             0.6432900
auc_czech                       0.6567842
auc_no                          0.6069959
auc_optimism_corrected          0.5391113
auc_optimism_corrected_CIL      0.4255404
auc_optimism_corrected_CIU      0.6354965
accuracy                        0.7608696
accuracy_czech                        NaN
accuracy_no                     0.7500000
accuracy_optimism_corrected     0.6881402
accuracy_optimism_corrected_CIL 0.6073201
accuracy_optimism_corrected_CIU 0.7746941
enet_model$conf_matrices
$original
    0  
0 105 0
1  33 0

$czech
   0  
0 78 0
1 24 0

$no
   0  
0 27 0
1  9 0
enet_model$plot


roc_c

rPSC vs healthy
group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 67 ASV(s)
Removing 4 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.2000000
lambda                          0.1466508
auc                             1.0000000
auc_czech                       1.0000000
auc_no                          1.0000000
auc_optimism_corrected          0.9240344
auc_optimism_corrected_CIL      0.8003744
auc_optimism_corrected_CIU      0.9821934
accuracy                        0.9811321
accuracy_czech                        NaN
accuracy_no                     0.9777778
accuracy_optimism_corrected     0.8625555
accuracy_optimism_corrected_CIL 0.7755383
accuracy_optimism_corrected_CIU 0.9328125
enet_model$conf_matrices
$original
    Predicted
True  0  1
   0 73  0
   1  2 31

$czech
    Predicted
True  0  1
   0 37  0
   1  1 23

$no
    Predicted
True  0  1
   0 36  0
   1  1  8
enet_model$plot


roc_c

non-rPSC vs healthy
group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,group, 
                                     usage="ml_clr")
Removing 24 ASV(s)
Removing 2 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.2000000
lambda                          0.0419208
auc                             1.0000000
auc_czech                       1.0000000
auc_no                          1.0000000
auc_optimism_corrected          0.9461298
auc_optimism_corrected_CIL      0.8722130
auc_optimism_corrected_CIU      0.9819748
accuracy                        1.0000000
accuracy_czech                        NaN
accuracy_no                     1.0000000
accuracy_optimism_corrected     0.8701671
accuracy_optimism_corrected_CIL 0.7972015
accuracy_optimism_corrected_CIU 0.9440068
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0  73   0
   1   0 105

$czech
    Predicted
True  0  1
   0 37  0
   1  0 78

$no
    Predicted
True  0  1
   0 36  0
   1  0 27
enet_model$plot

roc_c

rPSC effect
model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_genus_tab,
                                                ileum_genus_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.3616408
auc                             0.5000000
auc_czech                       0.5000000
auc_no                          0.5000000
auc_optimism_corrected          0.6729259
auc_optimism_corrected_CIL      0.6036558
auc_optimism_corrected_CIU      0.7434551
accuracy                        0.7608696
accuracy_czech                        NaN
accuracy_no                     0.7500000
accuracy_optimism_corrected     0.7604718
accuracy_optimism_corrected_CIL 0.6916360
accuracy_optimism_corrected_CIU 0.8096875
enet_model$conf_matrices
$original
    0  
0 105 0
1  33 0

$czech
   0  
0 78 0
1 24 0

$no
   0  
0 27 0
1  9 0
enet_model$plot


roc_c

Saving results

models_summ_df_ileum <- do.call(rbind, 
  models_summ[grep(segment,names(models_summ),value = TRUE)])

write.csv(models_summ_df_ileum,file.path(path,paste0("elastic_net_",segment,".csv")))

Supplementary models

supplements_models <- list()

CLR-transformed data

kNN
model="knn"
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               30.0000000
auc                              0.7075036
auc_optimism_corrected           0.5690333
auc_optimism_corrected_CIL       0.3766176
auc_optimism_corrected_CIU       0.6993946
accuracy                         0.7608696
accuracy_optimism_corrected      0.7565703
accuracy_optimism_corrected_CIL  0.6916360
accuracy_optimism_corrected_CIU  0.7916667
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)


# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 1214 ASV(s)
Removing 122 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs


# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               11.0000000
auc                              0.9618099
auc_optimism_corrected           0.8903596
auc_optimism_corrected_CIL       0.8195214
auc_optimism_corrected_CIU       0.9472403
accuracy                         0.8301887
accuracy_optimism_corrected      0.7865538
accuracy_optimism_corrected_CIL  0.6431652
accuracy_optimism_corrected_CIU  0.8817460
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 392 ASV(s)
Removing 91 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               30.0000000
auc                              0.9123940
auc_optimism_corrected           0.8432204
auc_optimism_corrected_CIL       0.7626955
auc_optimism_corrected_CIU       0.9176372
accuracy                         0.8426966
accuracy_optimism_corrected      0.7828159
accuracy_optimism_corrected_CIL  0.6389927
accuracy_optimism_corrected_CIU  0.8876080
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_asv_tab,
                                                ileum_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               15.0000000
auc                              0.7424242
auc_optimism_corrected           0.6372846
auc_optimism_corrected_CIL       0.5144382
auc_optimism_corrected_CIU       0.7584529
accuracy                         0.7753623
accuracy_optimism_corrected      0.7609173
accuracy_optimism_corrected_CIL  0.6960478
accuracy_optimism_corrected_CIU  0.8125000
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs


# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               30.0000000
auc                              0.6545455
auc_optimism_corrected           0.4773881
auc_optimism_corrected_CIL       0.3668218
auc_optimism_corrected_CIU       0.5755595
accuracy                         0.7608696
accuracy_optimism_corrected      0.7565703
accuracy_optimism_corrected_CIL  0.6916360
accuracy_optimism_corrected_CIU  0.7981250
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 67 ASV(s)
Removing 4 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs


# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               11.0000000
auc                              0.9798672
auc_optimism_corrected           0.8794371
auc_optimism_corrected_CIL       0.7240942
auc_optimism_corrected_CIU       0.9734677
accuracy                         0.7830189
accuracy_optimism_corrected      0.7505292
accuracy_optimism_corrected_CIL  0.6652256
accuracy_optimism_corrected_CIU  0.8442857
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 24 ASV(s)
Removing 2 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs


# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               11.0000000
auc                              0.9592955
auc_optimism_corrected           0.9016547
auc_optimism_corrected_CIL       0.8550021
auc_optimism_corrected_CIU       0.9489797
accuracy                         0.8483146
accuracy_optimism_corrected      0.7421026
accuracy_optimism_corrected_CIL  0.6488462
accuracy_optimism_corrected_CIU  0.8474315
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_genus_tab,
                                                ileum_genus_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               30.0000000
auc                              0.6939394
auc_optimism_corrected           0.5806831
auc_optimism_corrected_CIL       0.4759774
auc_optimism_corrected_CIU       0.7342562
accuracy                         0.7608696
accuracy_optimism_corrected      0.7466992
accuracy_optimism_corrected_CIL  0.6561581
accuracy_optimism_corrected_CIU  0.8096875
roc_c

Random Forest
model="rf"
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "121"      
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.5849764"
auc_optimism_corrected_CIL      "0.4977469"
auc_optimism_corrected_CIU      "0.6674945"
accuracy                        "1"        
accuracy_optimism_corrected     "0.758507" 
accuracy_optimism_corrected_CIL "0.6912377"
accuracy_optimism_corrected_CIU "0.8275641"
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 1214 ASV(s)
Removing 122 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "325"      
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9211468"
auc_optimism_corrected_CIL      "0.7937378"
auc_optimism_corrected_CIU      "0.972576" 
accuracy                        "1"        
accuracy_optimism_corrected     "0.8046381"
accuracy_optimism_corrected_CIL "0.6938995"
accuracy_optimism_corrected_CIU "0.8602183"
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 392 ASV(s)
Removing 91 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "87"       
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.8758431"
auc_optimism_corrected_CIL      "0.8091548"
auc_optimism_corrected_CIU      "0.9587847"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8426825"
accuracy_optimism_corrected_CIL "0.786062" 
accuracy_optimism_corrected_CIU "0.9341625"
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_asv_tab,
                                                ileum_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "3"        
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "0.9998557"
auc_optimism_corrected          "0.5509912"
auc_optimism_corrected_CIL      "0.3424858"
auc_optimism_corrected_CIU      "0.6863205"
accuracy                        "0.9927536"
accuracy_optimism_corrected     "0.7465253"
accuracy_optimism_corrected_CIL "0.7064338"
accuracy_optimism_corrected_CIU "0.7869668"
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "137"      
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.6037616"
auc_optimism_corrected_CIL      "0.4547491"
auc_optimism_corrected_CIU      "0.6788593"
accuracy                        "1"        
accuracy_optimism_corrected     "0.7519543"
accuracy_optimism_corrected_CIL "0.6865502"
accuracy_optimism_corrected_CIU "0.8258333"
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 67 ASV(s)
Removing 4 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "79"       
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9413444"
auc_optimism_corrected_CIL      "0.8586957"
auc_optimism_corrected_CIU      "0.981984" 
accuracy                        "1"        
accuracy_optimism_corrected     "0.8364897"
accuracy_optimism_corrected_CIL "0.6866541"
accuracy_optimism_corrected_CIU "0.9322768"
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 24 ASV(s)
Removing 2 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "99"       
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.9028857"
auc_optimism_corrected_CIL      "0.8299031"
auc_optimism_corrected_CIU      "0.9638187"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8669888"
accuracy_optimism_corrected_CIL "0.7925"   
accuracy_optimism_corrected_CIU "0.9550601"
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_genus_tab,
                                                ileum_genus_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "7"        
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.5992598"
auc_optimism_corrected_CIL      "0.5281838"
auc_optimism_corrected_CIU      "0.6611226"
accuracy                        "1"        
accuracy_optimism_corrected     "0.7549795"
accuracy_optimism_corrected_CIL "0.6912377"
accuracy_optimism_corrected_CIU "0.8046875"
roc_c

Gradient boosting
model="gb"
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.5174986
auc_optimism_corrected_CIL        0.4020749
auc_optimism_corrected_CIU        0.6121226
accuracy                          1.0000000
accuracy_optimism_corrected       0.7345733
accuracy_optimism_corrected_CIL   0.6916360
accuracy_optimism_corrected_CIU   0.7679720
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 1214 ASV(s)
Removing 122 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         100.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9177655
auc_optimism_corrected_CIL        0.8539862
auc_optimism_corrected_CIU        0.9568388
accuracy                          1.0000000
accuracy_optimism_corrected       0.8083337
accuracy_optimism_corrected_CIL   0.7415072
accuracy_optimism_corrected_CIU   0.8709821
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_clr")
Removing 392 ASV(s)
Removing 91 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   30.0000000
auc                               1.0000000
auc_optimism_corrected            0.9183323
auc_optimism_corrected_CIL        0.8789748
auc_optimism_corrected_CIU        0.9764957
accuracy                          1.0000000
accuracy_optimism_corrected       0.8562009
accuracy_optimism_corrected_CIL   0.8014516
accuracy_optimism_corrected_CIU   0.9186104
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_asv_tab,
                                                ileum_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         100.0000000
interaction.depth                 1.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               0.9161616
auc_optimism_corrected            0.6089129
auc_optimism_corrected_CIL        0.4836930
auc_optimism_corrected_CIU        0.6714232
accuracy                          0.8550725
accuracy_optimism_corrected       0.7623020
accuracy_optimism_corrected_CIL   0.7121936
accuracy_optimism_corrected_CIU   0.8241987
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   20.0000000
auc                               1.0000000
auc_optimism_corrected            0.5338402
auc_optimism_corrected_CIL        0.4365296
auc_optimism_corrected_CIU        0.6661672
accuracy                          1.0000000
accuracy_optimism_corrected       0.7037208
accuracy_optimism_corrected_CIL   0.6666667
accuracy_optimism_corrected_CIU   0.7421503
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 67 ASV(s)
Removing 4 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         100.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9409113
auc_optimism_corrected_CIL        0.8776902
auc_optimism_corrected_CIU        0.9854808
accuracy                          1.0000000
accuracy_optimism_corrected       0.8497037
accuracy_optimism_corrected_CIL   0.7726974
accuracy_optimism_corrected_CIU   0.9564955
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_clr")
Removing 24 ASV(s)
Removing 2 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9233013
auc_optimism_corrected_CIL        0.8738388
auc_optimism_corrected_CIU        0.9661456
accuracy                          1.0000000
accuracy_optimism_corrected       0.8521988
accuracy_optimism_corrected_CIL   0.7930597
accuracy_optimism_corrected_CIU   0.9070330
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_genus_tab,
                                                ileum_genus_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.6077735
auc_optimism_corrected_CIL        0.4459963
auc_optimism_corrected_CIU        0.7540255
accuracy                          1.0000000
accuracy_optimism_corrected       0.7337445
accuracy_optimism_corrected_CIL   0.6514706
accuracy_optimism_corrected_CIU   0.8208333
roc_c

Relative abundances

Elastic net
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.3152294
auc                             0.5779221
auc_czech                       0.5774573
auc_no                          0.5781893
auc_optimism_corrected          0.6000705
auc_optimism_corrected_CIL      0.5004649
auc_optimism_corrected_CIU      0.7793269
accuracy                        0.7608696
accuracy_czech                        NaN
accuracy_no                     0.7500000
accuracy_optimism_corrected     0.7528585
accuracy_optimism_corrected_CIL 0.6105699
accuracy_optimism_corrected_CIU 0.8394891
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 1214 ASV(s)
Removing 122 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.1081973
auc                             1.0000000
auc_czech                       1.0000000
auc_no                          1.0000000
auc_optimism_corrected          0.9529088
auc_optimism_corrected_CIL      0.8878711
auc_optimism_corrected_CIU      0.9894988
accuracy                        0.9905660
accuracy_czech                        NaN
accuracy_no                     0.9777778
accuracy_optimism_corrected     0.8597920
accuracy_optimism_corrected_CIL 0.7760628
accuracy_optimism_corrected_CIU 0.9045455
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)


# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 392 ASV(s)
Removing 91 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.60000000
lambda                          0.03782134
auc                             1.00000000
auc_czech                       1.00000000
auc_no                          1.00000000
auc_optimism_corrected          0.90635619
auc_optimism_corrected_CIL      0.82872212
auc_optimism_corrected_CIU      0.95835084
accuracy                        1.00000000
accuracy_czech                         NaN
accuracy_no                     1.00000000
accuracy_optimism_corrected     0.85064780
accuracy_optimism_corrected_CIL 0.77397643
accuracy_optimism_corrected_CIU 0.91861042
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_asv_tab,
                                                ileum_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.2328208
auc                             0.5000000
auc_czech                       0.5000000
auc_no                          0.5000000
auc_optimism_corrected          0.5690894
auc_optimism_corrected_CIL      0.4746083
auc_optimism_corrected_CIU      0.6652762
accuracy                        0.7608696
accuracy_czech                        NaN
accuracy_no                     0.7500000
accuracy_optimism_corrected     0.7504092
accuracy_optimism_corrected_CIL 0.6865502
accuracy_optimism_corrected_CIU 0.7981250
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.3212085
auc                             0.5000000
auc_czech                       0.5000000
auc_no                          0.5000000
auc_optimism_corrected          0.5898005
auc_optimism_corrected_CIL      0.4531015
auc_optimism_corrected_CIU      0.7474247
accuracy                        0.7608696
accuracy_czech                        NaN
accuracy_no                     0.7500000
accuracy_optimism_corrected     0.7403522
accuracy_optimism_corrected_CIL 0.6561581
accuracy_optimism_corrected_CIU 0.8318910
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)


# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 67 ASV(s)
Removing 4 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           1.00000000
lambda                          0.01972607
auc                             1.00000000
auc_czech                       1.00000000
auc_no                          1.00000000
auc_optimism_corrected          0.85174703
auc_optimism_corrected_CIL      0.66521739
auc_optimism_corrected_CIU      0.94274500
accuracy                        1.00000000
accuracy_czech                         NaN
accuracy_no                     1.00000000
accuracy_optimism_corrected     0.79372737
accuracy_optimism_corrected_CIL 0.67350478
accuracy_optimism_corrected_CIU 0.87098214
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 24 ASV(s)
Removing 2 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.40000000
lambda                          0.05642506
auc                             0.99791259
auc_czech                       0.99861400
auc_no                          0.99794239
auc_optimism_corrected          0.90921375
auc_optimism_corrected_CIL      0.83611111
auc_optimism_corrected_CIU      0.95998026
accuracy                        0.96067416
accuracy_czech                         NaN
accuracy_no                     0.96825397
accuracy_optimism_corrected     0.82634576
accuracy_optimism_corrected_CIL 0.75730769
accuracy_optimism_corrected_CIU 0.87977038
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_genus_tab,
                                                ileum_genus_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.4000000
lambda                          0.2045333
auc                             0.5000000
auc_czech                       0.5000000
auc_no                          0.5000000
auc_optimism_corrected          0.5361341
auc_optimism_corrected_CIL      0.4551996
auc_optimism_corrected_CIU      0.6820732
accuracy                        0.7608696
accuracy_czech                        NaN
accuracy_no                     0.7500000
accuracy_optimism_corrected     0.7661738
accuracy_optimism_corrected_CIL 0.6960478
accuracy_optimism_corrected_CIU 0.8114183
roc_c

kNN
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               13.0000000
auc                              0.6914863
auc_optimism_corrected           0.4364683
auc_optimism_corrected_CIL       0.3442543
auc_optimism_corrected_CIU       0.6062799
accuracy                         0.7536232
accuracy_optimism_corrected      0.7603292
accuracy_optimism_corrected_CIL  0.6916360
accuracy_optimism_corrected_CIU  0.8096875
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 1214 ASV(s)
Removing 122 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               13.0000000
auc                              0.8756746
auc_optimism_corrected           0.7384519
auc_optimism_corrected_CIL       0.5847403
auc_optimism_corrected_CIU       0.8909709
accuracy                         0.6981132
accuracy_optimism_corrected      0.6905598
accuracy_optimism_corrected_CIL  0.5667398
accuracy_optimism_corrected_CIU  0.7935714
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 392 ASV(s)
Removing 91 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               23.0000000
auc                              0.8599478
auc_optimism_corrected           0.7960201
auc_optimism_corrected_CIL       0.7319426
auc_optimism_corrected_CIU       0.8941088
accuracy                         0.7977528
accuracy_optimism_corrected      0.7173750
accuracy_optimism_corrected_CIL  0.6103846
accuracy_optimism_corrected_CIU  0.8006849
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_asv_tab,
                                                ileum_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               30.0000000
auc                              0.7507937
auc_optimism_corrected           0.6012685
auc_optimism_corrected_CIL       0.4582148
auc_optimism_corrected_CIU       0.7079090
accuracy                         0.7608696
accuracy_optimism_corrected      0.7445805
accuracy_optimism_corrected_CIL  0.6713542
accuracy_optimism_corrected_CIU  0.8070913
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               12.0000000
auc                              0.7204906
auc_optimism_corrected           0.5247021
auc_optimism_corrected_CIL       0.4504327
auc_optimism_corrected_CIU       0.6254728
accuracy                         0.7681159
accuracy_optimism_corrected      0.7526688
accuracy_optimism_corrected_CIL  0.6754902
accuracy_optimism_corrected_CIU  0.7916667
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 67 ASV(s)
Removing 4 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               11.0000000
auc                              0.8897883
auc_optimism_corrected           0.7275478
auc_optimism_corrected_CIL       0.5635054
auc_optimism_corrected_CIU       0.8718839
accuracy                         0.7641509
accuracy_optimism_corrected      0.7317397
accuracy_optimism_corrected_CIL  0.6065789
accuracy_optimism_corrected_CIU  0.8249554
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 24 ASV(s)
Removing 2 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               25.0000000
auc                              0.8847358
auc_optimism_corrected           0.8273708
auc_optimism_corrected_CIL       0.7218575
auc_optimism_corrected_CIU       0.8887756
accuracy                         0.8202247
accuracy_optimism_corrected      0.7458772
accuracy_optimism_corrected_CIL  0.6807692
accuracy_optimism_corrected_CIU  0.8203125
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_genus_tab,
                                                ileum_genus_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               13.0000000
auc                              0.7734488
auc_optimism_corrected           0.5463875
auc_optimism_corrected_CIL       0.3858295
auc_optimism_corrected_CIU       0.6525333
accuracy                         0.7753623
accuracy_optimism_corrected      0.7408946
accuracy_optimism_corrected_CIL  0.6865502
accuracy_optimism_corrected_CIU  0.7885417
roc_c

Random Forest
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "45"       
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.6294299"
auc_optimism_corrected_CIL      "0.5442163"
auc_optimism_corrected_CIU      "0.7521896"
accuracy                        "1"        
accuracy_optimism_corrected     "0.7583885"
accuracy_optimism_corrected_CIL "0.691636" 
accuracy_optimism_corrected_CIU "0.798125" 
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 1214 ASV(s)
Removing 122 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "283"      
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9400127"
auc_optimism_corrected_CIL      "0.8682876"
auc_optimism_corrected_CIU      "0.9915483"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8348226"
accuracy_optimism_corrected_CIL "0.7580357"
accuracy_optimism_corrected_CIU "0.8881746"
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 392 ASV(s)
Removing 91 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "65"       
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.909026" 
auc_optimism_corrected_CIL      "0.8608662"
auc_optimism_corrected_CIU      "0.9626096"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8424148"
accuracy_optimism_corrected_CIL "0.7595179"
accuracy_optimism_corrected_CIU "0.9007692"
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_asv_tab,
                                                ileum_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "1"        
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "0.9943723"
auc_optimism_corrected          "0.63524"  
auc_optimism_corrected_CIL      "0.5536503"
auc_optimism_corrected_CIU      "0.7122773"
accuracy                        "0.8623188"
accuracy_optimism_corrected     "0.7325812"
accuracy_optimism_corrected_CIL "0.6865502"
accuracy_optimism_corrected_CIU "0.7682127"
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "1"        
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.6340995"
auc_optimism_corrected_CIL      "0.560939" 
auc_optimism_corrected_CIU      "0.7418293"
accuracy                        "0.9057971"
accuracy_optimism_corrected     "0.7350835"
accuracy_optimism_corrected_CIL "0.6862745"
accuracy_optimism_corrected_CIU "0.7708333"
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 67 ASV(s)
Removing 4 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "203"      
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.9497313"
auc_optimism_corrected_CIL      "0.8715106"
auc_optimism_corrected_CIU      "0.9941356"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8596052"
accuracy_optimism_corrected_CIL "0.7941587"
accuracy_optimism_corrected_CIU "0.9322768"
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 24 ASV(s)
Removing 2 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "7"        
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.9295135"
auc_optimism_corrected_CIL      "0.8657029"
auc_optimism_corrected_CIU      "0.9839446"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8739723"
accuracy_optimism_corrected_CIL "0.8014516"
accuracy_optimism_corrected_CIU "0.9344505"
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_genus_tab,
                                                ileum_genus_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "1"        
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.6155945"
auc_optimism_corrected_CIL      "0.5505441"
auc_optimism_corrected_CIU      "0.711145" 
accuracy                        "0.8985507"
accuracy_optimism_corrected     "0.7484636"
accuracy_optimism_corrected_CIL "0.6514706"
accuracy_optimism_corrected_CIU "0.8309943"
roc_c

Gradient boosting
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         100.0000000
interaction.depth                 1.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               0.9927850
auc_optimism_corrected            0.5068135
auc_optimism_corrected_CIL        0.4057158
auc_optimism_corrected_CIU        0.5988107
accuracy                          0.9275362
accuracy_optimism_corrected       0.7426751
accuracy_optimism_corrected_CIL   0.6710784
accuracy_optimism_corrected_CIU   0.8096875
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 1214 ASV(s)
Removing 122 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9498809
auc_optimism_corrected_CIL        0.9147640
auc_optimism_corrected_CIU        0.9610390
accuracy                          1.0000000
accuracy_optimism_corrected       0.8697992
accuracy_optimism_corrected_CIL   0.7827778
accuracy_optimism_corrected_CIU   0.9342548
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_asv_tab,
                                     ileum_taxa_tab,
                                     ileum_metadata,
                                     group, usage="ml_ra")
Removing 392 ASV(s)
Removing 91 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 1.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9222032
auc_optimism_corrected_CIL        0.8621283
auc_optimism_corrected_CIU        0.9842776
accuracy                          1.0000000
accuracy_optimism_corrected       0.8424909
accuracy_optimism_corrected_CIL   0.7446429
accuracy_optimism_corrected_CIU   0.9167308
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_asv_tab,
                                                ileum_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 1127 ASV(s)
Removing 27 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         100.0000000
interaction.depth                 1.0000000
shrinkage                         0.1000000
n.minobsinnode                   20.0000000
auc                               0.8629149
auc_optimism_corrected            0.6394533
auc_optimism_corrected_CIL        0.5887956
auc_optimism_corrected_CIU        0.7095918
accuracy                          0.7971014
accuracy_optimism_corrected       0.7336972
accuracy_optimism_corrected_CIL   0.6912377
accuracy_optimism_corrected_CIU   0.7694547
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(ileum_asv_tab,
                             ileum_taxa_tab,
                             taxonomic_level = level)

ileum_genus_tab <- genus_data[[1]]
ileum_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   20.0000000
auc                               0.9985570
auc_optimism_corrected            0.4493813
auc_optimism_corrected_CIL        0.3608186
auc_optimism_corrected_CIU        0.5408939
accuracy                          0.9855072
accuracy_optimism_corrected       0.6803940
accuracy_optimism_corrected_CIL   0.6117034
accuracy_optimism_corrected_CIU   0.7307692
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 67 ASV(s)
Removing 4 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   20.0000000
auc                               1.0000000
auc_optimism_corrected            0.9270279
auc_optimism_corrected_CIL        0.8614764
auc_optimism_corrected_CIU        0.9870724
accuracy                          1.0000000
accuracy_optimism_corrected       0.8379402
accuracy_optimism_corrected_CIL   0.7424825
accuracy_optimism_corrected_CIU   0.9322768
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep(ileum_genus_tab,
                                     ileum_genus_taxa_tab,
                                     ileum_metadata,
                                     group, 
                                     usage="ml_ra")
Removing 24 ASV(s)
Removing 2 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 1.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9520042
auc_optimism_corrected_CIL        0.8997708
auc_optimism_corrected_CIU        0.9953416
accuracy                          1.0000000
accuracy_optimism_corrected       0.8951099
accuracy_optimism_corrected_CIL   0.8153846
accuracy_optimism_corrected_CIU   0.9646154
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_ileum_uni_data <- binomial_prep_psc_effect(ileum_genus_tab,
                                                ileum_genus_taxa_tab, 
                                                ileum_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 55 ASV(s)
Removing 2 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_ileum_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.6146849
auc_optimism_corrected_CIL        0.5088894
auc_optimism_corrected_CIU        0.7767575
accuracy                          1.0000000
accuracy_optimism_corrected       0.7447143
accuracy_optimism_corrected_CIL   0.6514706
accuracy_optimism_corrected_CIU   0.8088542
roc_c

Saving results

models_list <- list()

for (model_name in names(supplements_models$models_summ)){
  df <- do.call(rbind, supplements_models$models_summ[[model_name]])
  models_list[[model_name]] <- df
}

write.xlsx(models_list,
           file=file.path(path,paste0("supplements_models_",segment,".xlsx")),
           rowNames=TRUE)

Results overview

Alpha diversity

pc_observed[[segment]]
pc_shannon[[segment]]
pc_simpson[[segment]]
pc_pielou[[segment]]

Plots

alpha_div_plots[[paste(segment,"Country")]]

alpha_div_plots[[paste(segment,"Custom")]]

Beta diversity

Main results

pairwise_aitchison_raw[[paste("genus", segment)]]

PCA

pca_plots_list[[paste(segment,"genus custom")]]

Supplements

knitr::kable(supplements_beta[!grepl("PCoA",names(supplements_beta))],
             digits = 3,
             caption = "Supplementary PERMANOVA results")
Supplementary PERMANOVA results
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.251 1.208 0.008 0.241 0.241
rPSC vs healthy 1 0.813 4.432 0.039 0.001 0.002 **
non-rPSC vs healthy 1 1.241 6.538 0.034 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1.449 6.976 0.049 0.001 0.001 ***
rPSC vs healthy , Country 1 0.972 5.300 0.047 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.336 7.038 0.037 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.151 0.724 0.005 0.803 0.803
rPSC vs healthy : Country 1 0.287 1.572 0.014 0.067 0.100
non-rPSC vs healthy : Country 1 0.354 1.873 0.010 0.011 0.033 *
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.337 1.138 0.008 0.241 0.241
rPSC vs healthy 1 0.887 3.269 0.030 0.001 0.002 **
non-rPSC vs healthy 1 1.349 4.846 0.026 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1.460 4.927 0.035 0.001 0.001 ***
rPSC vs healthy , Country 1 1.092 4.023 0.036 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.476 5.300 0.029 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.242 0.817 0.006 0.823 0.823
rPSC vs healthy : Country 1 0.342 1.261 0.011 0.118 0.177
non-rPSC vs healthy : Country 1 0.445 1.604 0.009 0.014 0.042 *
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 316.296 1.176 0.008 0.071 0.071
rPSC vs healthy 1 830.867 2.897 0.027 0.001 0.002 **
non-rPSC vs healthy 1 1156.137 4.137 0.023 0.001 0.002 **
rPSC vs non-rPSC , Country 1 639.519 2.378 0.017 0.001 0.001 ***
rPSC vs healthy , Country 1 598.496 2.087 0.019 0.001 0.001 ***
non-rPSC vs healthy , Country 1 752.840 2.694 0.015 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 222.179 0.825 0.006 0.960 0.960
rPSC vs healthy : Country 1 262.783 0.916 0.008 0.746 0.960
non-rPSC vs healthy : Country 1 291.928 1.045 0.006 0.333 0.960
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.505 1.557 0.011 0.026 0.026 *
rPSC vs healthy 1 1.342 4.364 0.039 0.001 0.002 **
non-rPSC vs healthy 1 1.979 6.424 0.034 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1.444 4.451 0.032 0.001 0.001 ***
rPSC vs healthy , Country 1 1.059 3.444 0.031 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.394 4.525 0.024 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.333 1.027 0.007 0.386 0.386
rPSC vs healthy : Country 1 0.390 1.272 0.011 0.093 0.140
non-rPSC vs healthy : Country 1 0.447 1.456 0.008 0.036 0.108
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.518 1.318 0.009 0.029 0.029 *
rPSC vs healthy 1 1.117 2.934 0.027 0.001 0.002 **
non-rPSC vs healthy 1 1.607 4.216 0.023 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1.214 3.089 0.022 0.001 0.001 ***
rPSC vs healthy , Country 1 0.939 2.467 0.023 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.203 3.157 0.017 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.390 0.992 0.007 0.469 0.469
rPSC vs healthy : Country 1 0.430 1.130 0.010 0.131 0.196
non-rPSC vs healthy : Country 1 0.501 1.318 0.007 0.026 0.078

PCA

ggarrange(plotlist = supplements_beta[grepl("PCoA",names(supplements_beta))],
          labels=names(supplements_beta[grepl("PCoA",names(supplements_beta))]),
          font.label = list(size=5,face="plain"),
          ncol=2,nrow=3)

Univariate analysis

Number of significant taxa

knitr::kable(cbind(as.data.frame(lapply(list_intersections,nrow)),
      as.data.frame(lapply(rpsc_effect,nrow))) %>% t() %>% 
  `colnames<-`("Count") %>% 
  `rownames<-`(c(names(list_intersections),"PSC effect ASV","PSC effect Genus")),caption="Number of significant taxa")
Number of significant taxa
Count
terminal_ileum genus non-rPSC vs rPSC 0
terminal_ileum genus healthy vs rPSC 34
terminal_ileum genus healthy vs non-rPSC 25
terminal_ileum ASV non-rPSC vs rPSC 0
terminal_ileum ASV healthy vs rPSC 46
terminal_ileum ASV healthy vs non-rPSC 48
terminal_ileum phylum non-rPSC vs rPSC 0
terminal_ileum phylum rPSC vs healthy 3
terminal_ileum phylum healthy vs non-rPSC 3
PSC effect ASV 16
PSC effect Genus 19

Counts

# univar_list <- univariate_statistics(list_intersections,
#                                      psc_effect,
#                                      ileum_genus_asv_taxa_tab)
# 
# univar_df <- univar_list[[1]]
# wb <- univar_list[[2]]
# 
# # save the results
# saveWorkbook(wb,"results/Q1/DAA_final_terminal_ileum.xlsx", overwrite = TRUE)
# 
# # see the results
# univar_df

Machine learning

Main models

Summary

knitr::kable(models_summ_df_ileum %>% dplyr::select(
"alpha","lambda",
"auc_optimism_corrected",
"auc_optimism_corrected_CIL",
"auc_optimism_corrected_CIU"),
             digits=2,caption="Elastic net results")
Elastic net results
alpha lambda auc_optimism_corrected auc_optimism_corrected_CIL auc_optimism_corrected_CIU
rPSC vs non-rPSC ASV terminal_ileum 0.4 0.31 0.59 0.48 0.70
rPSC vs healthy ASV terminal_ileum 0.2 0.11 0.96 0.90 0.99
non-rPSC vs healthy ASV terminal_ileum 0.2 0.03 0.94 0.86 0.98
rPSC effect ASV terminal_ileum 0.4 0.27 0.66 0.52 0.77
rPSC vs non-rPSC genus terminal_ileum 0.4 0.31 0.54 0.43 0.64
rPSC vs healthy genus terminal_ileum 0.2 0.15 0.92 0.80 0.98
non-rPSC vs healthy genus terminal_ileum 0.2 0.04 0.95 0.87 0.98
rPSC effect genus terminal_ileum 0.4 0.36 0.67 0.60 0.74

ROC - ASV level

roc_curve_all_custom(roc_cs[c(1:4)], 
                     Q="Q2",
                     model_name="enet_model")
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values

ROC - Genus level

roc_curve_all_custom(roc_cs[c(5:8)],Q="Q2",
                     model_name="enet_model")
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values

Supplementary models

Summary

# Build final dataframe
models_list[["enet_model"]] <- models_summ_df_ileum
final_df <- tibble(row_names = rownames(models_list[[1]]))

# Loop through models and extract required values
for (model_name in names(models_list)) {
  model_df <- models_list[[model_name]]
  
  # Combine AUC_optimism_corrected with its CI values
  final_df[[model_name]] <- paste0(
    round(model_df$auc_optimism_corrected, 3), 
    " (", round(model_df$auc_optimism_corrected_CIL, 3), "; ", 
    round(model_df$auc_optimism_corrected_CIU, 3), ")"
  )
}

knitr::kable(final_df, caption="All models")
All models
row_names knn_model rf_model gbm_model enet_model_ra knn_model_ra rf_model_ra gbm_model_ra enet_model
rPSC vs non-rPSC ASV terminal_ileum 0.569 (0.377; 0.699) 0.585 (0.498; 0.667) 0.517 (0.402; 0.612) 0.6 (0.5; 0.779) 0.436 (0.344; 0.606) 0.629 (0.544; 0.752) 0.507 (0.406; 0.599) 0.593 (0.477; 0.697)
rPSC vs healthy ASV terminal_ileum 0.89 (0.82; 0.947) 0.921 (0.794; 0.973) 0.918 (0.854; 0.957) 0.953 (0.888; 0.989) 0.738 (0.585; 0.891) 0.94 (0.868; 0.992) 0.95 (0.915; 0.961) 0.957 (0.896; 0.986)
non-rPSC vs healthy ASV terminal_ileum 0.843 (0.763; 0.918) 0.876 (0.809; 0.959) 0.918 (0.879; 0.976) 0.906 (0.829; 0.958) 0.796 (0.732; 0.894) 0.909 (0.861; 0.963) 0.922 (0.862; 0.984) 0.936 (0.864; 0.978)
rPSC effect ASV terminal_ileum 0.637 (0.514; 0.758) 0.551 (0.342; 0.686) 0.609 (0.484; 0.671) 0.569 (0.475; 0.665) 0.601 (0.458; 0.708) 0.635 (0.554; 0.712) 0.639 (0.589; 0.71) 0.655 (0.52; 0.767)
rPSC vs non-rPSC genus terminal_ileum 0.477 (0.367; 0.576) 0.604 (0.455; 0.679) 0.534 (0.437; 0.666) 0.59 (0.453; 0.747) 0.525 (0.45; 0.625) 0.634 (0.561; 0.742) 0.449 (0.361; 0.541) 0.539 (0.426; 0.635)
rPSC vs healthy genus terminal_ileum 0.879 (0.724; 0.973) 0.941 (0.859; 0.982) 0.941 (0.878; 0.985) 0.852 (0.665; 0.943) 0.728 (0.564; 0.872) 0.95 (0.872; 0.994) 0.927 (0.861; 0.987) 0.924 (0.8; 0.982)
non-rPSC vs healthy genus terminal_ileum 0.902 (0.855; 0.949) 0.903 (0.83; 0.964) 0.923 (0.874; 0.966) 0.909 (0.836; 0.96) 0.827 (0.722; 0.889) 0.93 (0.866; 0.984) 0.952 (0.9; 0.995) 0.946 (0.872; 0.982)
rPSC effect genus terminal_ileum 0.581 (0.476; 0.734) 0.599 (0.528; 0.661) 0.608 (0.446; 0.754) 0.536 (0.455; 0.682) 0.546 (0.386; 0.653) 0.616 (0.551; 0.711) 0.615 (0.509; 0.777) 0.673 (0.604; 0.743)

ROC - ASV

rocs_list <- supplements_models$roc_cs
rocs_list[["enet_model"]] <- roc_cs

plot_list <- list()

for (model_name in names(rocs_list)) {
  plot_list[[model_name]] <- roc_curve_all_custom(rocs_list[[model_name]][c(1:4)],
                       Q="Q2",
                       model_name=model_name)
}
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
ggarrange(plotlist = plot_list,labels = names(rocs_list),font.label = list(face="plain",size=7))

ROC - genus

plot_list <- list()

for (model_name in names(rocs_list)) {
  plot_list[[model_name]] <- roc_curve_all_custom(rocs_list[[model_name]][c(5:8)],
                       Q="Q2",
                       model_name=model_name)
}
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
p <- ggarrange(plotlist = plot_list,labels = names(rocs_list),font.label = list(face="plain",size=7))
p

pdf("../figures/Q2/models_ileum.pdf",
    height =10,width = 10)
p
dev.off()

Analysis - Colon

segment="colon"

Filtering

Rules: - prevalence > 5% (per group) - nearZeroVar with default settings - sequencing depth > 5000 - taxonomic assignment at least order

Rarefaction Curve

path="../intermediate_files/rarecurves"
seq_depth_threshold <- 10000
ps <- construct_phyloseq(colon_asv_tab,colon_taxa_tab,colon_metadata)
rareres <- get_rarecurve(obj=ps, chunks=500)
save(rareres,file = file.path(path,"rarefaction_colon.Rdata"))
load(file.path(path,"rarefaction_colon.Rdata"))
seq_depth_threshold <- 10000
prare <- ggrarecurve(obj=rareres,
                      factorNames="Country",
                      indexNames=c("Observe")) + 
        theme_bw()+
        theme(axis.text=element_text(size=8), 
              panel.grid=element_blank(),
              strip.background = element_rect(colour=NA,fill="grey"),
              strip.text.x = element_text(face="bold")) + 
        geom_vline(xintercept = seq_depth_threshold, 
                   linetype="dashed", color = "red") + 
        xlim(0, 20000)
Warning: NaNs producedThe color has been set automatically, you can reset it manually by adding scale_color_manual(values=yourcolors)
prare

Library size

read_counts(colon_asv_tab, line = c(5000,10000))
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.

Sequencing depth

data_filt <- seq_depth_filtering(colon_asv_tab,
                                 colon_taxa_tab,
                                 colon_metadata,
                                 seq_depth_threshold = 10000)
Removing 50 ASV(s)
filt_colon_asv_tab <- data_filt[[1]]; alpha_colon_asv_tab <- filt_colon_asv_tab
filt_colon_taxa_tab <- data_filt[[2]]; alpha_colon_taxa_tab <- filt_colon_taxa_tab
filt_colon_metadata <- data_filt[[3]]; alpha_colon_metadata <- filt_colon_metadata

seq_step <- dim(filt_colon_asv_tab)[1]

Library size

read_counts(filt_colon_asv_tab,line = c(10000))
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.

NearZeroVar

data_filt <- nearzerovar_filtering(filt_colon_asv_tab,
                                   filt_colon_taxa_tab,
                                   filt_colon_metadata)

filt_colon_asv_tab <- data_filt[[1]]
filt_colon_taxa_tab <- data_filt[[2]]
nearzero_step <- dim(filt_colon_asv_tab)[1]

Library size

read_counts(filt_colon_asv_tab,line = c(5000,10000))
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.

Check zero depth

data_filt <- check_zero_depth(filt_colon_asv_tab, 
                              filt_colon_taxa_tab, 
                              filt_colon_metadata)

filt_colon_asv_tab <- data_filt[[1]]; 
filt_colon_taxa_tab <- data_filt[[2]]; 
filt_colon_metadata <- data_filt[[3]]; 

Library size

read_counts(filt_colon_asv_tab,line = c(5000,10000))
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.

Final Counts

final_counts_filtering(colon_asv_tab,
                       filt_colon_asv_tab,
                       filt_colon_metadata,
                       seq_step, 0, nearzero_step)

Alpha diversity

path = "../results/Q2/alpha_diversity"

Calculation

# Construct MPSE object
alpha_colon_metadata$Sample <- alpha_colon_metadata$SampleID
colon_mpse <- as.MPSE(construct_phyloseq(alpha_colon_asv_tab,
                                         alpha_colon_taxa_tab,
                                         alpha_colon_metadata))

colon_mpse %<>% mp_rrarefy(raresize = 10000,seed = 123)

# Calculate alpha diversity - rarefied counts
colon_mpse %<>% mp_cal_alpha(.abundance=RareAbundance, force=TRUE)
alpha_data <- data.frame(SampleID=colon_mpse$Sample.x,
                         Observe=colon_mpse$Observe,
                         Shannon=colon_mpse$Shannon,
                         Simpson=colon_mpse$Simpson,
                         Pielou=colon_mpse$Pielou,
                         Group=colon_mpse$Group,
                         Country=colon_mpse$Country,
                         Patient=colon_mpse$Patient)

write.csv(alpha_data,file.path(path,paste0("alpha_indices_",segment,".csv")),
          row.names = FALSE)

Plots

Country plot

p_boxplot_alpha <- alpha_diversity_countries(alpha_data)
Using SampleID, Group, Country, Patient as id variables
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.Using SampleID, Group, Country, Patient as id variables
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.
# save the results
alpha_div_plots[[paste(segment,"Country")]] <- p_boxplot_alpha

# see the results
p_boxplot_alpha

pdf("../figures/Q2/alpha_diversity_colon.pdf",
    height =4,width = 7)
p_boxplot_alpha
dev.off()

Custom plot

alpha_data <- alpha_data %>% 
  dplyr::select(-c("Simpson","Pielou")) %>%
  mutate(Richness=Observe)

p_B <- alpha_diversity_custom_2(alpha_data,
                                size = 1.5,
                                width = 0.3)
Scale for y is already present.
Adding another scale for y, which will replace the existing scale.Scale for y is already present.
Adding another scale for y, which will replace the existing scale.
# save the results
alpha_div_plots[[paste(segment,"Custom")]] <- p_B

p_B

Linear Model

path = "../results/Q2/alpha_diversity"
alpha_data <- read.csv(file.path(path,paste0("alpha_indices_",segment,".csv")))

Richness

results_model <- pairwise.lmer(
  formula = "Observe ~ Group * Country + (1|Patient)",
  factors=alpha_data$Group,
  data=alpha_data)

# check interaction
if (!is.data.frame(results_model)){
  results_model_observe <- results_model[[1]]
  results_model_observe_detailed <- results_model[[2]]
} else {
  results_model_observe <- results_model
  results_model_observe_detailed <- NA
}

# save the results
pc_observed[[segment]] <- results_model_observe
# see the results
knitr::kable(results_model_observe,digits = 3,
caption = "Raw results of linear model of richness estimation.")
Raw results of linear model of richness estimation.
Estimate Std..Error df t.value Pr…t.. p.adj sig
non-rPSC vs GrouprPSC -17.252 12.469 156.883 -1.384 0.168 0.192
non-rPSC vs rPSC - CZ vs NO -17.941 10.644 153.303 -1.686 0.094 0.192
non-rPSC vs GrouprPSC:CountryNO 3.483 21.371 152.108 0.163 0.871 0.871
healthy vs GrouprPSC -40.307 11.924 125.516 -3.380 0.001 0.009 **
healthy vs rPSC - CZ vs NO 14.783 10.544 126.613 1.402 0.163 0.192
healthy vs GrouprPSC:CountryNO -29.232 19.769 123.028 -1.479 0.142 0.192
healthy vs Groupnon-rPSC -22.976 8.905 211.354 -2.580 0.011 0.047 *
healthy vs non-rPSC - CZ vs NO 14.961 10.892 212.956 1.374 0.171 0.192
healthy vs Groupnon-rPSC:CountryNO -32.911 14.701 208.353 -2.239 0.026 0.079

knitr::kable(results_model_observe_detailed,digits = 3,
caption = "Raw results of independent country analysis")
Raw results of independent country analysis
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 171.507 6.650 77.696 25.792 0.000 NA
GrouprPSC -40.316 11.792 76.971 -3.419 0.001 0.002
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 186.301 8.264 48.971 22.543 0 NA
GrouprPSC -69.557 16.036 46.963 -4.338 0 0
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 171.468 6.275 89.628 27.325 0.000 NA
CountryNO 14.904 9.836 89.468 1.515 0.133 0.178
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 131.179 11.294 36.279 11.615 0.000 NA
CountryNO -14.435 19.236 35.739 -0.750 0.458 0.458
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 171.439 6.808 137.314 25.182 0.000 NA
Groupnon-rPSC -22.949 8.722 135.888 -2.631 0.009 0.019
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 186.365 8.682 75.472 21.467 0 NA
Groupnon-rPSC -55.850 12.120 73.619 -4.608 0 0
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 171.468 6.275 89.628 27.325 0.000 NA
CountryNO 14.904 9.836 89.468 1.515 0.133 0.133
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 148.477 5.932 120.279 25.028 0.000 NA
CountryNO -17.950 10.519 117.183 -1.706 0.091 0.121

Shannon

results_model <- pairwise.lmer(
  formula = "Shannon ~ Group * Country + (1|Patient)",
  factors=alpha_data$Group,
  data=alpha_data)

# check interaction
if (!is.data.frame(results_model)){
  results_model_shannon <- results_model[[1]]
  results_model_shannon_detailed <- results_model[[2]]
} else {
  results_model_shannon <- results_model
  results_model_shannon_detailed <- NA
}

# save the results
pc_shannon[[segment]] <- as.data.frame(results_model_shannon)
# see the results
knitr::kable(results_model_shannon,digits = 3,
caption = "Raw results of linear model of Shannon estimation.")
Raw results of linear model of Shannon estimation.
Estimate Std..Error df t.value Pr…t.. p.adj sig
non-rPSC vs GrouprPSC -0.146 0.161 154.485 -0.907 0.366 0.549
non-rPSC vs rPSC - CZ vs NO -0.355 0.138 151.788 -2.581 0.011 0.051
non-rPSC vs GrouprPSC:CountryNO 0.008 0.277 150.856 0.030 0.976 0.976
healthy vs GrouprPSC -0.330 0.128 126.201 -2.572 0.011 0.051
healthy vs rPSC - CZ vs NO 0.017 0.113 127.217 0.146 0.884 0.976
healthy vs GrouprPSC:CountryNO -0.364 0.213 123.907 -1.709 0.090 0.162
healthy vs Groupnon-rPSC -0.182 0.101 207.051 -1.795 0.074 0.162
healthy vs non-rPSC - CZ vs NO 0.018 0.124 208.617 0.145 0.884 0.976
healthy vs Groupnon-rPSC:CountryNO -0.375 0.168 204.129 -2.240 0.026 0.078

knitr::kable(results_model_shannon_detailed,digits = 3,
caption = "Raw results of independent country analysis")
Raw results of independent country analysis
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 3.683 0.065 77.802 56.300 0.000 NA
GrouprPSC -0.330 0.116 76.679 -2.846 0.006 0.011
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 3.700 0.099 48.693 37.40 0.000 NA
GrouprPSC -0.693 0.193 47.827 -3.59 0.001 0.003
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 3.683 0.054 89.061 68.505 0.000 NA
CountryNO 0.019 0.084 88.828 0.231 0.818 0.818
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 3.354 0.153 36.206 21.939 0.000 NA
CountryNO -0.347 0.261 35.912 -1.332 0.191 0.255
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 3.684 0.081 133.503 45.582 0.000 NA
Groupnon-rPSC -0.184 0.104 132.547 -1.772 0.079 0.105
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 3.702 0.093 77.069 39.853 0 NA
Groupnon-rPSC -0.559 0.129 74.201 -4.324 0 0
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 3.683 0.054 89.061 68.505 0.000 NA
CountryNO 0.019 0.084 88.828 0.231 0.818 0.818
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 3.501 0.075 117.089 46.588 0.000 NA
CountryNO -0.357 0.133 114.586 -2.673 0.009 0.017

Simpson

results_model <- pairwise.lmer(
  formula = "Simpson ~ Group * Country + (1|Patient)",
  factors=alpha_data$Group,
  data=alpha_data)

# check interaction
if (!is.data.frame(results_model)){
  results_model_simpson <- results_model[[1]]
  results_model_simpson_detailed <- results_model[[2]]
} else {
  results_model_simpson <- results_model
  results_model_simpson_detailed <- NA
}

# save the results
pc_simpson[[segment]] <- as.data.frame(results_model_simpson)
# see the results
knitr::kable(results_model_simpson,digits = 3,
caption = "Raw results of linear model of Simpson estimation.")
Raw results of linear model of Simpson estimation.
Estimate Std..Error df t.value Pr…t.. p.adj sig
non-rPSC vs GrouprPSC -0.005 0.029 153.608 -0.169 0.866 0.866
non-rPSC vs rPSC - CZ vs NO -0.032 0.024 151.251 -1.296 0.197 0.443
non-rPSC vs GrouprPSC:CountryNO -0.027 0.049 150.427 -0.554 0.581 0.806
healthy vs GrouprPSC -0.031 0.020 127.660 -1.523 0.130 0.391
healthy vs rPSC - CZ vs NO -0.007 0.018 128.411 -0.402 0.688 0.806
healthy vs GrouprPSC:CountryNO -0.052 0.034 125.982 -1.540 0.126 0.391
healthy vs Groupnon-rPSC -0.026 0.016 201.924 -1.600 0.111 0.391
healthy vs non-rPSC - CZ vs NO -0.007 0.020 203.469 -0.363 0.717 0.806
healthy vs Groupnon-rPSC:CountryNO -0.025 0.026 199.046 -0.952 0.342 0.616

knitr::kable(results_model_simpson_detailed,digits = 3,
caption = "Raw results of independent country analysis")
Raw results of independent country analysis
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.944 0.008 79.314 121.920 0.000 NA
GrouprPSC -0.031 0.014 77.978 -2.245 0.028 0.057
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.936 0.019 48.621 50.151 0.000 NA
GrouprPSC -0.082 0.037 48.125 -2.258 0.029 0.057
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.943 0.004 90.956 214.963 0.000 NA
CountryNO -0.007 0.007 90.564 -0.990 0.325 0.325
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.913 0.029 36.306 31.229 0.000 NA
CountryNO -0.059 0.050 36.048 -1.181 0.245 0.325

Pielou

results_model <- pairwise.lmer(
  formula = "Pielou ~ Group * Country + (1|Patient)",
  factors=alpha_data$Group,
  data=alpha_data)

# check interaction
if (!is.data.frame(results_model)){
  results_model_pielou <- results_model[[1]]
  results_model_pielou_detailed <- results_model[[2]]
} else {
  results_model_pielou <- results_model
  results_model_pielou_detailed <- NA
}

# save the results
pc_pielou[[segment]] <- as.data.frame(results_model_pielou)
# see the results
knitr::kable(results_model_pielou,digits = 3,
caption = "Raw results of linear model of Pielou estimation.")
Raw results of linear model of Pielou estimation.
Estimate Std..Error df t.value Pr…t.. p.adj sig
non-rPSC vs GrouprPSC -0.007 0.026 153.863 -0.292 0.771 0.843
non-rPSC vs rPSC - CZ vs NO -0.052 0.022 150.735 -2.372 0.019 0.171
non-rPSC vs GrouprPSC:CountryNO -0.009 0.044 149.674 -0.198 0.843 0.843
healthy vs GrouprPSC -0.023 0.020 127.665 -1.183 0.239 0.538
healthy vs rPSC - CZ vs NO -0.008 0.017 129.013 -0.457 0.648 0.843
healthy vs GrouprPSC:CountryNO -0.052 0.033 124.565 -1.605 0.111 0.333
healthy vs Groupnon-rPSC -0.015 0.015 204.651 -1.006 0.316 0.568
healthy vs non-rPSC - CZ vs NO -0.008 0.019 206.473 -0.416 0.678 0.843
healthy vs Groupnon-rPSC:CountryNO -0.044 0.025 201.171 -1.745 0.083 0.333

knitr::kable(results_model_pielou_detailed,digits = 3,
caption = "Raw results of independent country analysis")
Raw results of independent country analysis
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.720 0.009 78.395 76.134 0.000 NA
GrouprPSC -0.023 0.017 77.018 -1.392 0.168 0.224
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.712 0.016 49.474 44.366 0.000 NA
GrouprPSC -0.076 0.031 47.962 -2.424 0.019 0.077
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.720 0.007 89.185 99.650 0.000 NA
CountryNO -0.008 0.011 88.856 -0.667 0.506 0.506
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.697 0.025 36.449 27.771 0.000 NA
CountryNO -0.060 0.043 35.950 -1.414 0.166 0.224
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.720 0.013 132.894 56.00 0.000 NA
Groupnon-rPSC -0.016 0.016 132.038 -0.97 0.334 0.445
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.713 0.013 79.537 55.174 0.000 NA
Groupnon-rPSC -0.060 0.018 74.995 -3.379 0.001 0.005
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.720 0.007 89.185 99.650 0.000 NA
CountryNO -0.008 0.011 88.856 -0.667 0.506 0.506
Estimate Std. Error df t value Pr(>|t|) p.adjusted
(Intercept) 0.705 0.012 115.555 60.129 0.000 NA
CountryNO -0.052 0.021 112.732 -2.499 0.014 0.028

Saving results

alpha_list <- list(
  Richness=pc_observed[[segment]] %>% rownames_to_column("Comparison"),
  Shannon=pc_shannon[[segment]] %>% rownames_to_column("Comparison"),
  Simpson=pc_simpson[[segment]] %>% rownames_to_column("Comparison"),
  Pielou=pc_pielou[[segment]] %>% rownames_to_column("Comparison"))
                   
write.xlsx(alpha_list, 
           file = file.path(path,paste0("alpha_diversity_results_",segment,".xlsx")))

Beta diversity

Calculating Aitchison distance (euclidean distance on clr-transformed data), both at ASV and genus level.

Main analysis - Genus, Aitchison

Genus level, Aitchison distance

level="genus"
path = "../results/Q2/beta_diversity"

Aggregation, filtering

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level=level,
                             names=TRUE)

filt_data <- filtering_steps(genus_data[[1]],
                             genus_data[[2]],
                             colon_metadata,
                            seq_depth_threshold=10000)
Removing 5 ASV(s)
filt_colon_genus_tab <- filt_data[[1]]
filt_colon_genus_taxa <- filt_data[[2]]
filt_colon_genus_metadata <- filt_data[[3]]
PERMANOVA
pairwise_df <- filt_colon_genus_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,filt_colon_genus_metadata$Group,
                           covariate = filt_colon_genus_metadata$Country, 
                           patients = filt_colon_genus_metadata$Patient,
                           sim.method = "robust.aitchison", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,filt_colon_genus_metadata$Group,
                          covariate = filt_colon_genus_metadata$Country, 
                          interaction = TRUE, 
                          patients = filt_colon_genus_metadata$Patient,
                          sim.method = "robust.aitchison", p.adjust.m="BH")

# tidy the results
pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
pairwise_aitchison_raw[[paste(level, segment)]] <-rbind(pp_factor,pp_cov,pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 419.973 2.475 0.007 0.415 0.415
rPSC vs healthy 1 1473.966 8.988 0.035 0.001 0.002 **
non-rPSC vs healthy 1 1742.331 10.401 0.024 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 1556.933 9.177 0.026 0.001 0.001 ***
rPSC vs healthy , Country 1 883.284 5.386 0.021 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1558.672 9.304 0.021 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 318.175 1.880 0.005 0.970 0.970
rPSC vs healthy : Country 1 319.594 1.956 0.008 0.820 0.970
non-rPSC vs healthy : Country 1 407.191 2.439 0.006 0.163 0.489

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

if (length(interaction_sig)>0){
 for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_colon_genus_metadata$Group,
                      covariate = filt_colon_genus_metadata$Country, 
                      group1 = group1,
                      group2 = group2,
                      patients = filt_colon_genus_metadata$Patient)
  print(result_list)
} 
}
Plots

PCoA custom

p <- pca_plot_custom(filt_colon_genus_tab,
                                 filt_colon_genus_taxa,
                                 filt_colon_genus_metadata,
                                 show_boxplots = TRUE,
                                 variable = "Group", size=2, 
                                 show_legend=FALSE)

# save the results
pca_plots_list[[paste(segment,level,"custom")]] <- p

# see the results
p

pdf("../figures/Q2/beta_diversity_colon.pdf",
    height =5,width = 5)
p
dev.off()

Saving results

write.xlsx(pairwise_aitchison_raw[[paste(level, segment)]], 
           file = file.path(path,
           paste0("beta_diversity_results_", segment,".xlsx")))

Supplementary analysis

Genus level

level="genus"
Bray-Curtis

PERMANOVA

pairwise_df <- filt_colon_genus_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,
                           filt_colon_genus_metadata$Group,
                           covariate = filt_colon_genus_metadata$Country, 
                           patients = filt_colon_genus_metadata$Patient,
                           sim.method = "bray", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,
                          filt_colon_genus_metadata$Group,
                          covariate = filt_colon_genus_metadata$Country, 
                          patients = filt_colon_genus_metadata$Patient,
                          interaction = TRUE, sim.method = "bray", p.adjust.m="BH")

# tidy the results
pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("bray",level,segment)]] <- rbind(pp_factor,pp_cov,pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.504 2.488 0.007 0.267 0.267
rPSC vs healthy 1 2.464 13.675 0.051 0.001 0.002 **
non-rPSC vs healthy 1 3.227 18.295 0.039 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 5.037 24.881 0.066 0.001 0.001 ***
rPSC vs healthy , Country 1 2.136 11.852 0.044 0.001 0.001 ***
non-rPSC vs healthy , Country 1 4.670 26.476 0.057 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 0.446 2.209 0.006 0.460 0.460
rPSC vs healthy : Country 1 0.495 2.765 0.010 0.102 0.153
non-rPSC vs healthy : Country 1 1.025 5.881 0.012 0.001 0.003 **

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_colon_genus_metadata$Group,
                      covariate = filt_colon_genus_metadata$Country, 
                      patients = filt_colon_genus_metadata$Patient,
                      group1 = group1,
                      group2 = group2,
                      sim.method = 'bray')
  print(result_list)
}
$`non-rPSC_healthy_CZ`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1    1.415 0.03183 8.3495  0.001      0.001
Residual 254   43.052 0.96817                         
Total    255   44.467 1.00000                         

$`non-rPSC_healthy_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1    2.837 0.08594 15.607  0.001      0.001
Residual 166   30.175 0.91406                         
Total    167   33.012 1.00000                         

$`non-rPSC_CZ_vs_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs     R2      F Pr(>F) p.adjusted
Cov        1    4.273 0.0792 22.449  0.001      0.001
Residual 261   49.683 0.9208                         
Total    262   53.956 1.0000                         

$healthy_CZ_vs_NO
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov        1   1.4216 0.05694 9.6009  0.001      0.001
Residual 159  23.5437 0.94306                         
Total    160  24.9653 1.00000                         

Plots

p <- pca_plot_custom(filt_colon_genus_tab,
                                 filt_colon_genus_taxa,
                                 filt_colon_genus_metadata,
                                 measure = "bray",
                                 show_boxplots = TRUE,
                                 variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA bray",level,segment)]] <- p

# see the results
p

Jaccard

PERMANOVA

pairwise_df <- filt_colon_genus_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,
                           filt_colon_genus_metadata$Group,
                           covariate = filt_colon_genus_metadata$Country,
                           patients = filt_colon_genus_metadata$Patient,
                           sim.method = "jaccard", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,
                          filt_colon_genus_metadata$Group,
                          covariate = filt_colon_genus_metadata$Country,
                          patients = filt_colon_genus_metadata$Patient,
                          interaction = TRUE, sim.method = "jaccard", p.adjust.m="BH")

# tidy the results
pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("jaccard",level,segment)]] <- rbind(pp_factor, 
                                                            pp_cov, 
                                                            pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.590 2.035 0.006 0.594 0.594
rPSC vs healthy 1 2.438 9.075 0.035 0.001 0.002 **
non-rPSC vs healthy 1 3.380 12.658 0.028 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 4.994 17.225 0.047 0.001 0.001 ***
rPSC vs healthy , Country 1 2.338 8.704 0.033 0.001 0.001 ***
non-rPSC vs healthy , Country 1 4.864 18.215 0.040 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 0.589 2.039 0.006 0.696 0.696
rPSC vs healthy : Country 1 0.632 2.365 0.009 0.208 0.312
non-rPSC vs healthy : Country 1 1.174 4.433 0.010 0.001 0.003 **

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_colon_genus_metadata$Group,
                      covariate = filt_colon_genus_metadata$Country, 
                      patients = filt_colon_genus_metadata$Patient,
                      group1 = group1,
                      group2 = group2,
                      sim.method = 'jaccard')
  print(result_list)
}
$`non-rPSC_healthy_CZ`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1    1.591 0.02354 6.1232  0.001      0.001
Residual 254   65.982 0.97646                         
Total    255   67.573 1.00000                         

$`non-rPSC_healthy_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1    2.963 0.06145 10.869  0.001      0.001
Residual 166   45.256 0.93855                         
Total    167   48.219 1.00000                         

$`non-rPSC_CZ_vs_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov        1    4.325 0.05591 15.458  0.001      0.001
Residual 261   73.032 0.94409                         
Total    262   77.358 1.00000                         

$healthy_CZ_vs_NO
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs     R2      F Pr(>F) p.adjusted
Cov        1    1.712 0.0429 7.1261  0.001      0.001
Residual 159   38.206 0.9571                         
Total    160   39.918 1.0000                         

Plots

Custom

p <- pca_plot_custom(filt_colon_genus_tab,
                                 filt_colon_genus_taxa,
                                 filt_colon_genus_metadata,
                                 measure = "jaccard",
                                 show_boxplots = TRUE,
                                 variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA jaccard",level,segment)]] <- p

# see the results
p

ASV level

level="ASV"
Aitchison
# preparing data frame
pairwise_df <- filt_colon_asv_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(x=pairwise_df,
                          filt_colon_metadata$Group,
                           covariate = filt_colon_metadata$Country, 
                           sim.method = "robust.aitchison", 
                           p.adjust.m="BH",
                           patients = filt_colon_metadata$Patient)

# interaction
pp_int <- pairwise.adonis(pairwise_df,filt_colon_metadata$Group,
                          covariate = filt_colon_metadata$Country, 
                          interaction = TRUE, 
                          sim.method = "robust.aitchison", 
                          p.adjust.m="BH",
                          patients = filt_colon_metadata$Patient)

pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("aitchison",level,segment)]] <- rbind(pp_factor, 
                                                            pp_cov, 
                                                            pp_fac.cov)

# see the results
pp_factor
pp_cov
pp_fac.cov
NA
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 470.424 1.893 0.005 0.968 0.968
rPSC vs healthy 1 1842.677 6.979 0.027 0.001 0.002 **
non-rPSC vs healthy 1 2475.754 9.500 0.022 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 1644.116 6.616 0.019 0.001 0.001 ***
rPSC vs healthy , Country 1 1119.321 4.239 0.017 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1833.401 7.035 0.016 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 470.881 1.900 0.005 0.989 0.989
rPSC vs healthy : Country 1 517.888 1.969 0.008 0.896 0.989
non-rPSC vs healthy : Country 1 611.799 2.355 0.005 0.163 0.489

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

if (length(interaction_sig)>0){
 for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_colon_metadata$Group,
                      covariate = filt_colon_metadata$Country, 
                      group1 = group1,
                      group2 = group2,
                      patients = filt_colon_metadata$Patient)
  print(result_list)
} 
}

PCoA

p <- pca_plot_custom(filt_colon_asv_tab,
                           filt_colon_taxa_tab,
                           filt_colon_metadata,
                           show_boxplots = TRUE,
                           variable = "Group", 
                           size=3, 
                           show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA aitchison",level,segment)]] <- p

# see the results
p

Bray-Curtis

PERMANOVA

# preparing data frame
pairwise_df <- filt_colon_asv_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,
                           filt_colon_metadata$Group,
                           covariate = filt_colon_metadata$Country,
                           patients = filt_colon_metadata$Patient,
                           sim.method = "bray", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,
                          filt_colon_metadata$Group,
                          covariate = filt_colon_metadata$Country, 
                          patients = filt_colon_metadata$Patient,
                          interaction = TRUE, sim.method = "bray", p.adjust.m="BH")

pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("bray",level,segment)]] <- rbind(pp_factor, 
                                                            pp_cov, 
                                                            pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.737 2.327 0.006 0.415 0.415
rPSC vs healthy 1 3.308 10.870 0.041 0.001 0.002 **
non-rPSC vs healthy 1 4.794 16.082 0.036 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 4.600 14.526 0.040 0.001 0.001 ***
rPSC vs healthy , Country 1 2.184 7.177 0.027 0.001 0.001 ***
non-rPSC vs healthy , Country 1 4.330 14.527 0.032 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 0.792 2.512 0.007 0.383 0.383
rPSC vs healthy : Country 1 0.815 2.697 0.010 0.145 0.217
non-rPSC vs healthy : Country 1 1.360 4.601 0.010 0.002 0.006 **

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_colon_metadata$Group,
                      covariate = filt_colon_metadata$Country, 
                      group1 = group1,
                      group2 = group2,
                      patients = filt_colon_metadata$Patient,
                      sim.method = 'bray')
  print(result_list)
}
$`non-rPSC_healthy_CZ`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs    R2      F Pr(>F) p.adjusted
Fac        1    2.255 0.029 7.5854  0.001      0.001
Residual 254   75.510 0.971                         
Total    255   77.765 1.000                         

$`non-rPSC_healthy_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1    3.899 0.07422 13.309  0.001      0.001
Residual 166   48.631 0.92578                         
Total    167   52.530 1.00000                         

$`non-rPSC_CZ_vs_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov        1    4.042 0.04823 13.227  0.001      0.001
Residual 261   79.749 0.95177                         
Total    262   83.790 1.00000                         

$healthy_CZ_vs_NO
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov        1    1.649 0.03581 5.9053  0.001      0.001
Residual 159   44.393 0.96419                         
Total    160   46.041 1.00000                         

PCoA

p <- pca_plot_custom(filt_colon_asv_tab,
                     filt_colon_taxa_tab,
                     filt_colon_metadata,
                     measure = "bray",
                     show_boxplots = TRUE,
                     variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA bray",level,segment)]] <- p

# see the results
p

Jaccard

PERMANOVA

# preparing data frame
pairwise_df <- filt_colon_asv_tab %>% column_to_rownames("SeqID") %>% t()

# main effect
pp_main <- pairwise.adonis(pairwise_df,
                           filt_colon_metadata$Group,
                           covariate = filt_colon_metadata$Country,
                           patients = filt_colon_metadata$Patient,
                           sim.method = "jaccard", p.adjust.m="BH")

# interaction
pp_int <- pairwise.adonis(pairwise_df,
                          filt_colon_metadata$Group,
                          covariate = filt_colon_metadata$Country, 
                          patients = filt_colon_metadata$Patient,
                          interaction = TRUE, sim.method = "jaccard", p.adjust.m="BH")

pp_factor <- pp_main[[1]]
pp_cov <- pp_main[[2]]
pp_fac.cov <- pp_int[[3]]

cols <- c("pairs","Df","SumsOfSqs", "F.Model","R2","p.value", "p.adjusted", "sig")
colnames(pp_factor) <- cols; colnames(pp_cov) <- cols; colnames(pp_fac.cov) <- cols; 

# save raw results
supplements_beta[[paste("jaccard",level,segment)]] <- rbind(pp_factor, 
                                                            pp_cov, 
                                                            pp_fac.cov)
# see the results
knitr::kable(pp_factor,digits = 3,caption = "PERMANOVA, GROUP separation")
PERMANOVA, GROUP separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.737 1.909 0.005 0.873 0.873
rPSC vs healthy 1 2.563 6.794 0.026 0.001 0.002 **
non-rPSC vs healthy 1 3.757 10.047 0.023 0.001 0.002 **
knitr::kable(pp_cov,digits = 3,caption = "PERMANOVA, COUNTRY separation")
PERMANOVA, COUNTRY separation
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC , Country 1 3.698 9.578 0.027 0.001 0.001 ***
rPSC vs healthy , Country 1 1.887 5.001 0.019 0.001 0.001 ***
non-rPSC vs healthy , Country 1 3.508 9.381 0.021 0.001 0.001 ***
knitr::kable(pp_fac.cov,digits = 3,caption = "PERMANOVA, INTERACTION GROUP:Country")
PERMANOVA, INTERACTION GROUP:Country
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC : Country 1 0.814 2.115 0.006 0.822 0.822
rPSC vs healthy : Country 1 0.853 2.271 0.009 0.388 0.582
non-rPSC vs healthy : Country 1 1.296 3.486 0.008 0.002 0.006 **

Interaction check

interaction_sig <- pp_fac.cov$pairs[pp_fac.cov$p.adjusted < 0.05]

for (i in 1:length(interaction_sig)){
  group1 <- unlist(strsplit(interaction_sig[i],split = " vs "))[1]
  group2 <- unlist(strsplit(interaction_sig[i],split = " vs "))[2]
  group2 <- unlist(strsplit(group2,split = " : "))[1]
  
  result_list <- adonis_postanalysis(x=pairwise_df,
                      factors = filt_colon_metadata$Group,
                      covariate = filt_colon_metadata$Country, 
                      patients = filt_colon_metadata$Patient,
                      group1 = group1,
                      group2 = group2,
                      sim.method = 'jaccard')
  print(result_list)
}
$`non-rPSC_healthy_CZ`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1    1.890 0.01954 5.0623  0.001      0.001
Residual 254   94.839 0.98046                         
Total    255   96.729 1.00000                         

$`non-rPSC_healthy_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Fac, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Fac        1    3.163 0.04907 8.5656  0.001      0.001
Residual 166   61.293 0.95093                         
Total    167   64.456 1.00000                         

$`non-rPSC_CZ_vs_NO`
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov        1    3.288 0.03219 8.6816  0.001      0.001
Residual 261   98.853 0.96781                         
Total    262  102.141 1.00000                         

$healthy_CZ_vs_NO
Permutation test for adonis under reduced model
Terms added sequentially (first to last)
Permutation: supplied matrix
Number of permutations: 999

adonis2(formula = x1 ~ Cov, data = x2, permutations = perm)
          Df SumOfSqs      R2      F Pr(>F) p.adjusted
Cov        1    1.516 0.02578 4.2075  0.001      0.001
Residual 159   57.279 0.97422                         
Total    160   58.794 1.00000                         

PCoA

p <- pca_plot_custom(filt_colon_asv_tab,
                     filt_colon_taxa_tab,
                     filt_colon_metadata,
                     measure = "jaccard",
                     show_boxplots = TRUE,
                     variable = "Group", size=3, show_legend=FALSE)

# save the results
supplements_beta[[paste("PCoA jaccard",level,segment)]] <- p

# see the results
p

Saving results

write.xlsx(supplements_beta[!grepl("PCoA",names(supplements_beta))],
           file = file.path(path,
           paste0("supplements_beta_diversity_", segment,".xlsx")))

Univariate Analysis

Main - Genus level

level="genus"
# needed paths
path = "../results/Q2/univariate_analysis"
path_maaslin=file.path("../intermediate_files/maaslin/Q2",level)
# variables

raw_linda_results_genus[[segment]] <- list()
linda_results_genus[[segment]] <- list()

# country and interaction problems
list_country_union <- list()
list_intersections <- list()
list_venns <- list()
uni_statistics <- list()

# workbook for final df
wb <- createWorkbook()

# PSC effect

Genus level

rpsc_effect <- list()

Aggregate taxa

level="genus"
genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]

colon_genus_asv_taxa_tab <- create_asv_taxa_table(colon_genus_tab,
                                                  colon_genus_taxa_tab)
rPSC vs non-rPSC
linDA
group <- c("non-rPSC","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

# prepare the data
linda_data <- binomial_prep(colon_genus_tab,
                            colon_genus_taxa_tab,
                            colon_metadata,
                            group, usage="linDA")
Removing 28 ASV(s)
Removing 5 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data,
                   filt_colon_uni_metadata,
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  350  samples and  166  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")


for (grp in c(group1,group2,group3)){
  raw_linda_results_genus[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results_genus[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1, 
                                taxa_table = filt_colon_uni_taxa) + 
            ggtitle(paste(group,collapse=" vs "))

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_colon_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2
volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
Warning: Removed 3 rows containing missing values or values outside the scale
range (`geom_text_repel()`).Warning: Removed 12 rows containing missing values or values outside the scale
range (`geom_text_repel()`).
volcano

Group - Intersection
intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_genus, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union
list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)
Interaction effect
list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_colon_uni_data,
                                          filt_colon_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)
Basic statistics
uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_genus[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "non-rPSC"
[1] "rPSC"
[1] "non-rPSC"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- comparison_name
addWorksheet(wb, sheetName = new_name)
writeData(wb, sheet = new_name, uni_df, rowNames=FALSE)

rPSC vs healthy

group <- c("healthy","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
linDA

# prepare the data
linda_data <- binomial_prep(colon_genus_tab,
                            colon_genus_taxa_tab,
                            colon_metadata,
                            group, usage="linDA")
Removing 98 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data,
                   filt_colon_uni_metadata,
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  248  samples and  178  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results_genus[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results_genus[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1, 
                                taxa_table = filt_colon_uni_taxa) + 
            ggtitle(paste(group,collapse=" vs "))

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_colon_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2
volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
Warning: Removed 31 rows containing missing values or values outside the scale
range (`geom_text_repel()`).Warning: Removed 12 rows containing missing values or values outside the scale
range (`geom_text_repel()`).
volcano

Group - Intersection
intersection_results <- group_intersection(group, 
                                           list_intersections, 
                                           list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_genus, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union
list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)
Interaction effect
list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_colon_uni_data,
                                          filt_colon_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)
Basic statistics
uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_genus[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "rPSC"
[1] "healthy"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- comparison_name
addWorksheet(wb, sheetName = new_name)
writeData(wb, sheet = new_name, uni_df, rowNames=FALSE)
non-rPSC vs healthy
group <- c("healthy","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
linDA

# prepare the data
linda_data <- binomial_prep(colon_genus_tab,
                            colon_genus_taxa_tab,
                            colon_metadata,group,
                            usage="linDA")
Removing 39 ASV(s)
Removing 6 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data,
                   filt_colon_uni_metadata,
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  424  samples and  159  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results_genus[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results_genus[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1, 
                                taxa_table = filt_colon_uni_taxa) + 
            ggtitle(paste(group,collapse=" vs "))

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                taxa_table = filt_colon_uni_taxa) + 
            ggtitle("Country effect") 

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) +
            ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2
volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
Warning: Removed 29 rows containing missing values or values outside the scale
range (`geom_text_repel()`).Warning: Removed 19 rows containing missing values or values outside the scale
range (`geom_text_repel()`).
volcano

Group - Intersection
intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results_genus, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union
list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)
Interaction effect
list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_colon_uni_data,
                                          filt_colon_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)
Basic statistics
uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results_genus[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "non-rPSC"
[1] "healthy"
[1] "non-rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- comparison_name
addWorksheet(wb, sheetName = new_name)
writeData(wb, sheet = new_name, uni_df, rowNames=FALSE)
Visualization

Heatmap visualizing the linDA’s logFoldChange for taxa with p < 0.1.

list_heatmap <- list_intersections[grep(paste(segment,level),
                                  names(list_intersections),value=TRUE)]

p_heatmap_linda <- heatmap_linda(list_heatmap,colon_taxa_tab)
p_heatmap_linda

Dot heatmap

dotheatmap_linda <- dot_heatmap_linda(list_heatmap,
                                      uni_statistics$colon[grepl(level,names(uni_statistics$colon))],
                                      colon_taxa_tab) + xlab("") + ylab("")
min_clr -2.080021 
max_clr 6.901023 
min_log -4.181218 
max_log 3.872081 
dotheatmap_linda

Horizontal bar plot

p_prevalence <- horizontal_barplot(wb,taxa=levels(dotheatmap_linda$data$SeqID))
Using SeqID as id variables

pdf("../figures/Q2/dotplot_colon.pdf",
    height =10,width = 4)
p
dev.off()
rPSC effect

pre_LTx vs Healthy and Post_LTx vs Healthy intersection

A <- list_intersections[[paste(segment,level,"healthy vs rPSC")]]
B <- list_intersections[[paste(segment,level,"healthy vs non-rPSC")]]
df <- A[!(A$SeqID %in% B$SeqID),]

rpsc_effect[[paste(segment,level)]] <- df
  
# see the results
rpsc_effect[[paste(segment,level)]] 

Saving results

# ALL DATA
saveWorkbook(wb,file.path(path,paste0("uni_analysis_wb_",segment,".xlsx")),
             overwrite = TRUE)

# PSC effect
write.xlsx(rpsc_effect[[paste(segment,level)]],file.path(path,paste0("rpsc_effect_",segment,".xlsx")))

# SIGNIFICANT taxa

write.xlsx(list_intersections[grepl(segment,names(list_intersections))] %>%
            `names<-`(gsub(segment, "", names(
              list_intersections[grepl(segment,names(list_intersections))]))),
           file.path(path,paste0("significant_taxa_",segment,".xlsx")))

Supplementary Analysis

ASV level

level="ASV"
path_maaslin="../intermediate_files/maaslin/Q2/ASV/"
raw_linda_results[[segment]] <- list()
linda_results[[segment]] <- list()
supplements_wb <- createWorkbook()
rPSC vs non-rPSC
group <- c("non-rPSC","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(colon_asv_tab,
                            colon_taxa_tab,
                            colon_metadata,
                            group, usage="linDA")
Removing 1358 ASV(s)
Removing 17 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data, 
                   filt_colon_uni_metadata, 
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  350  samples and  336  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1,
                                taxa_table = filt_colon_uni_taxa) +
              ggtitle(paste(group,collapse=" vs "))

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                 taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Country effect")

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2

Volcano plot

volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") +
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)

# see the results
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                                                                      segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                                    filt_colon_uni_data,
                                                    filt_colon_uni_metadata,
                                                    segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "non-rPSC"
[1] "rPSC"
[1] "non-rPSC"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
rPSC vs healthy
group <- c("healthy","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(colon_asv_tab,colon_taxa_tab,
                            colon_metadata,group, usage="linDA")
Removing 1644 ASV(s)
Removing 43 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data, 
                   filt_colon_uni_metadata, 
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  248  samples and  438  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1,
                                taxa_table = filt_colon_uni_taxa) +
              ggtitle(paste(group,collapse=" vs "))

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                 taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Country effect")

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") +
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)

# see the results
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                           segment=segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_colon_uni_data,
                                          filt_colon_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                               segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "rPSC"
[1] "healthy"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
non-rPSC vs healthy
group <- c("healthy","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(colon_asv_tab,
                            colon_taxa_tab,
                            colon_metadata,
                            group, usage="linDA")
Removing 527 ASV(s)
Removing 54 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data, 
                   filt_colon_uni_metadata,
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  423  samples and  383  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1,
                                taxa_table = filt_colon_uni_taxa) +
              ggtitle(paste(group,collapse=" vs "))

volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                 taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Country effect")

volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Interaction")

volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_colon_uni_data,
                                          filt_colon_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "non-rPSC"
[1] "healthy"
[1] "non-rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
Visualization

Heatmap visualizing the linDA’s logFoldChange for taxa with p < 0.1.

list_heatmap <- list_intersections[grep(paste(segment,level),
                                  names(list_intersections),value=TRUE)]

p_heatmap_linda <- heatmap_linda(list_heatmap,colon_taxa_tab)
p_heatmap_linda

Dot heatmap

dotheatmap_linda <- dot_heatmap_linda(list_heatmap,
                                      uni_statistics$colon[grepl(level,names(uni_statistics$colon))],
                                      colon_taxa_tab)
min_clr -1.227991 
max_clr 4.635178 
min_log -5.321387 
max_log 6.195274 
dotheatmap_linda

rPSC effect

pre_LTx vs Healthy and Post_LTx vs Healthy intersection

A <- list_intersections[[paste(segment,level,"healthy vs rPSC")]]
B <- list_intersections[[paste(segment,level,"healthy vs non-rPSC")]]
df <- A[!(A$SeqID %in% B$SeqID),]

rpsc_effect[[paste(segment,level)]] <- df
  
# see the results
rpsc_effect[[paste(segment,level)]] 

Phylum level

level="phylum"
path_maaslin="../intermediate_files/maaslin/Q2/Phylum/"
raw_linda_results_phylum[[segment]] <- list()
linda_results_phylum[[segment]] <- list()

Aggregate taxa

phylum_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = "Phylum")

colon_phylum_tab <- phylum_data[[1]]
colon_phylum_taxa_tab <- phylum_data[[2]]
rPSC vs non-rPSC
group <- c("non-rPSC","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(colon_phylum_tab,
                            colon_phylum_taxa_tab,
                            colon_metadata,
                            group, usage="linDA")
Removing 1 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data, 
                   filt_colon_uni_metadata, 
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  350  samples and  10  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1,
                                taxa_table = filt_colon_uni_taxa) +
              ggtitle(paste(group,collapse=" vs "))
Using Phylum for naming
volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                 taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Country effect")
Using Phylum for naming
volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Interaction")
Using Phylum for naming
volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2

Volcano plot

volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") +
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)

# see the results
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                                                                      segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                                    filt_colon_uni_data,
                                                    filt_colon_uni_metadata,
                                                    segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "non-rPSC"
[1] "rPSC"
[1] "non-rPSC"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
rPSC vs healthy
group <- c("healthy","rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(colon_phylum_tab,
                            colon_phylum_taxa_tab,
                            colon_metadata,group, usage="linDA")
Removing 2 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data, 
                   filt_colon_uni_metadata, 
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  248  samples and  10  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1,
                                taxa_table = filt_colon_uni_taxa) +
              ggtitle(paste(group,collapse=" vs "))
Using Phylum for naming
volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                 taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Country effect")
Using Phylum for naming
volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Interaction")
Using Phylum for naming
volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") +
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)

# see the results
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                           segment=segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_colon_uni_data,
                                          filt_colon_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                               segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "rPSC"
[1] "healthy"
[1] "rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
non-rPSC vs healthy
group <- c("healthy","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])

linDA


# prepare the data
linda_data <- binomial_prep(colon_phylum_tab,
                            colon_phylum_taxa_tab,
                            colon_metadata,
                            group, usage="linDA")
Removing 2 ASV(s)
filt_colon_uni_data <- linda_data[[1]]
filt_colon_uni_taxa <- linda_data[[2]]
filt_colon_uni_metadata <- linda_data[[3]]

# fit the model
linda.obj <- linda(filt_colon_uni_data, 
                   filt_colon_uni_metadata,
                   formula = '~ Group * Country + (1|Patient)')
0  features are filtered!
The filtered data has  424  samples and  9  features will be tested!
Imputation approach is used.
Fit linear mixed effects models ...
Completed.
linda.output <- linda.obj$output
linda.output <- linda_renaming(linda.output, group)

# save the results
group1 <- paste0(group[1], " vs ","Group",group[2])
group2 <- paste0(group[1], " , ",group[2], " - CZ vs NO") 
group3 <- paste0(group[1], " vs ","Group",group[2], ":CountryNO")

for (grp in c(group1,group2,group3)){
  raw_linda_results[[segment]][[grp]] <- 
    rawlinda.df(linda.output,
                grp,
                filt_colon_uni_data,
                filt_colon_uni_taxa)
  
  linda_results[[segment]][[grp]] <- 
    linda.df(linda.output,
             grp,
             filt_colon_uni_data,
             filt_colon_uni_taxa)
}
# volcano plot
volcano_1 <- volcano_plot_linda(linda.output, group1,
                                taxa_table = filt_colon_uni_taxa) +
              ggtitle(paste(group,collapse=" vs "))
Using Phylum for naming
volcano_2  <- volcano_plot_linda(linda.output, group2, 
                                 taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Country effect")
Using Phylum for naming
volcano_3 <- volcano_plot_linda(linda.output, group3, 
                                taxa_table = filt_colon_uni_taxa) + 
              ggtitle("Interaction")
Using Phylum for naming
volcano <- ggarrange(volcano_1,volcano_2,volcano_3, ncol=3)

# see the plot
volcano

MaAsLin2

volcano1 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa) + 
            ggtitle(paste(group[1], "vs", group[2]))

volcano2 <- volcano_plot_maaslin(fit_data,filt_colon_uni_taxa,variable="Country") + 
            ggtitle("Country effect")

volcano <- ggarrange(volcano1,volcano2, ncol=2)
volcano

Group - Intersection

intersection_results <- group_intersection(group, list_intersections, list_venns,
                                           linda.output, fit_data,
                                           raw_linda_results, 
                                           segment = segment,
                                           level=level)

list_intersections <- intersection_results[[1]]
list_venns <- intersection_results[[2]]
venn <- intersection_results[[3]]

# show the results
venn

Country - Union

list_country_union <- country_union(group,linda.output, fit_data,
                                    segment=segment,
                                    level=level)

Interaction effect

list_interaction_significant <- country_interaction(group,
                                                    linda.output, 
                                                    list_intersections,
                                          filt_colon_uni_data,
                                          filt_colon_uni_metadata,
                                          segment=segment,
                                          level=level)

# see the result
## significant interaction effect
list_interaction_significant[[1]]
NULL
## results for czech cohort
list_interaction_significant[[2]]
[1] NA
## results for norwegian cohort
list_interaction_significant[[3]]
[1] NA

Removing problematic taxa

list_intersections <- removing_interaction_problems(group,
                                                    list_interaction_significant,
                                                    list_intersections,
                                                    segment=segment,
                                                    level=level)

Basic statistics

uni_df <-  merge(basic_univariate_statistics(linda_data,group),
                 raw_linda_results[[segment]][[group1]],
                 by="SeqID",all=TRUE)
[1] "healthy"
[1] "non-rPSC"
[1] "healthy"
[1] "non-rPSC"
uni_df[["final_sig"]] <- uni_df$SeqID %in% list_intersections[[paste(segment,level,comparison_name)]][["SeqID"]]
uni_statistics[[segment]][[paste(level,comparison_name)]] <- uni_df

# for comparison
new_name <- paste(level,comparison_name)
addWorksheet(supplements_wb, sheetName = new_name)
writeData(supplements_wb, sheet = new_name, uni_df, rowNames=FALSE)
Visualization

Heatmap visualizing the linDA’s logFoldChange for taxa with p < 0.1.

list_heatmap <- list_intersections[grep(paste(segment,level),
                                  names(list_intersections),value=TRUE)]

p_heatmap_linda <- heatmap_linda(list_heatmap,colon_taxa_tab)
p_heatmap_linda

Dot heatmap

dotheatmap_linda <- dot_heatmap_linda(list_heatmap,
                                      uni_statistics$colon[grepl(level,names(uni_statistics$colon))],
                                      colon_taxa_tab)
min_clr -4.222255 
max_clr 4.824442 
min_log -3.334323 
max_log 3.037521 
dotheatmap_linda

rPSC effect

pre_LTx vs Healthy and Post_LTx vs Healthy intersection

A <- list_intersections[[paste(segment,level,"healthy vs rPSC")]]
B <- list_intersections[[paste(segment,level,"healthy vs non-rPSC")]]
df <- A[!(A$SeqID %in% B$SeqID),]

rpsc_effect[[paste(segment,level)]] <- df
  
# see the results
rpsc_effect[[paste(segment,level)]] 

Saving results

# ALL DATA
saveWorkbook(supplements_wb,file.path(path,paste0("supplements_uni_analysis_wb_",segment,".xlsx")),overwrite = TRUE)

# PSC effect
write.xlsx(rpsc_effect,
          file.path(path,paste0("supplements_rpsc_effect_",segment,".xlsx")))

# SIGNIFICANT taxa
write.xlsx(list_intersections[grepl(segment,names(list_intersections))] %>%
            `names<-`(gsub(segment, "", names(
              list_intersections[grepl(segment,names(list_intersections))]))),
           file.path(path,paste0("supplements_significant_taxa_",segment,".xlsx")))

Machine learning

path = "../results/Q2/models"

ElasticNet

model="enet"

ASV level

level="ASV"
rPSC vs non-rPSC
group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.20000000
lambda                          0.02642212
auc                             0.99995630
auc_czech                       0.99987060
auc_no                          1.00000000
auc_optimism_corrected          0.68930277
auc_optimism_corrected_CIL      0.58182584
auc_optimism_corrected_CIU      0.79550463
accuracy                        0.99714286
accuracy_czech                         NaN
accuracy_no                     1.00000000
accuracy_optimism_corrected     0.75877572
accuracy_optimism_corrected_CIL 0.72626823
accuracy_optimism_corrected_CIU 0.79732143
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0 262   1
   1   0  87

$czech
    Predicted
True   0   1
   0 160   1
   1   0  48

$no
    Predicted
True   0   1
   0 102   0
   1   0  39
enet_model$plot

roc_c

rPSC vs healthy
group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 1644 ASV(s)
Removing 43 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                       [,1]
alpha                           0.800000000
lambda                          0.004696739
auc                             1.000000000
auc_czech                       1.000000000
auc_no                          1.000000000
auc_optimism_corrected          0.984090282
auc_optimism_corrected_CIL      0.963868802
auc_optimism_corrected_CIU      0.999092742
accuracy                        1.000000000
accuracy_czech                          NaN
accuracy_no                     1.000000000
accuracy_optimism_corrected     0.913881132
accuracy_optimism_corrected_CIL 0.847549020
accuracy_optimism_corrected_CIU 0.973152174
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0 161   0
   1   0  87

$czech
    Predicted
True  0  1
   0 95  0
   1  0 48

$no
    Predicted
True  0  1
   0 66  0
   1  0 39
enet_model$plot


roc_c

non-rPSC vs healthy
group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 527 ASV(s)
Removing 54 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                       [,1]
alpha                           0.600000000
lambda                          0.005254429
auc                             1.000000000
auc_czech                       1.000000000
auc_no                          1.000000000
auc_optimism_corrected          0.956087245
auc_optimism_corrected_CIL      0.923453896
auc_optimism_corrected_CIU      0.978627881
accuracy                        1.000000000
accuracy_czech                          NaN
accuracy_no                     1.000000000
accuracy_optimism_corrected     0.884857150
accuracy_optimism_corrected_CIL 0.822568090
accuracy_optimism_corrected_CIU 0.926187201
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0 161   0
   1   0 262

$czech
    Predicted
True   0   1
   0  95   0
   1   0 160

$no
    Predicted
True   0   1
   0  66   0
   1   0 102
enet_model$plot


roc_c

rPSC effect
model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_asv_tab,
                                                colon_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.8000000
lambda                          0.0217535
auc                             0.9212447
auc_czech                       0.9039855
auc_no                          0.9441931
auc_optimism_corrected          0.7892446
auc_optimism_corrected_CIL      0.7051772
auc_optimism_corrected_CIU      0.8440312
accuracy                        0.8400000
accuracy_czech                        NaN
accuracy_no                     0.8865248
accuracy_optimism_corrected     0.7720808
accuracy_optimism_corrected_CIL 0.7394864
accuracy_optimism_corrected_CIU 0.7990527
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0 254   9
   1  47  40

$czech
    Predicted
True   0   1
   0 152   9
   1  31  17

$no
    Predicted
True   0   1
   0 102   0
   1  16  23
enet_model$plot


roc_c

Genus level

level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]
rPSC vs non-rPSC
group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.00000000
lambda                          0.03550553
auc                             0.99707181
auc_czech                       0.99495342
auc_no                          1.00000000
auc_optimism_corrected          0.61631007
auc_optimism_corrected_CIL      0.52956470
auc_optimism_corrected_CIU      0.73363312
accuracy                        0.98571429
accuracy_czech                         NaN
accuracy_no                     0.98581560
accuracy_optimism_corrected     0.69300993
accuracy_optimism_corrected_CIL 0.62137380
accuracy_optimism_corrected_CIU 0.73052686
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0 262   1
   1   4  83

$czech
    Predicted
True   0   1
   0 160   1
   1   2  46

$no
    Predicted
True   0   1
   0 102   0
   1   2  37
enet_model$plot


roc_c

rPSC vs healthy
group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 98 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                        [,1]
alpha                           0.8000000000
lambda                          0.0001910911
auc                             1.0000000000
auc_czech                       1.0000000000
auc_no                          1.0000000000
auc_optimism_corrected          0.9578010737
auc_optimism_corrected_CIL      0.9109651085
auc_optimism_corrected_CIU      0.9970643939
accuracy                        1.0000000000
accuracy_czech                           NaN
accuracy_no                     1.0000000000
accuracy_optimism_corrected     0.9191192622
accuracy_optimism_corrected_CIL 0.8130021521
accuracy_optimism_corrected_CIU 0.9849584399
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0 161   0
   1   0  87

$czech
    Predicted
True  0  1
   0 95  0
   1  0 48

$no
    Predicted
True  0  1
   0 66  0
   1  0 39
enet_model$plot


roc_c

rPSC vs healthy
group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 39 ASV(s)
Removing 6 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group",
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                       [,1]
alpha                           0.200000000
lambda                          0.002866942
auc                             1.000000000
auc_czech                       1.000000000
auc_no                          1.000000000
auc_optimism_corrected          0.964410427
auc_optimism_corrected_CIL      0.941685324
auc_optimism_corrected_CIU      0.986722684
accuracy                        1.000000000
accuracy_czech                          NaN
accuracy_no                     1.000000000
accuracy_optimism_corrected     0.902089871
accuracy_optimism_corrected_CIL 0.854318182
accuracy_optimism_corrected_CIU 0.925430657
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0 161   0
   1   0 263

$czech
    Predicted
True   0   1
   0  95   0
   1   0 161

$no
    Predicted
True   0   1
   0  66   0
   1   0 102
enet_model$plot

roc_c

rPSC effect
model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_genus_tab,
                                                colon_genus_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
models_summ[[model_name]] <- enet_model$model_summary
models_cm[[model_name]] <- enet_model$conf_matrices$original
roc_cs[[model_name]] <- enet_model$kfold_rocobjs
betas[[model_name]] <- as.matrix(enet_model$betas)

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.60000000
lambda                          0.05398387
auc                             0.81010445
auc_czech                       0.80421843
auc_no                          0.80869784
auc_optimism_corrected          0.74403921
auc_optimism_corrected_CIL      0.70796536
auc_optimism_corrected_CIU      0.77093481
accuracy                        0.80571429
accuracy_czech                         NaN
accuracy_no                     0.78014184
accuracy_optimism_corrected     0.74738866
accuracy_optimism_corrected_CIL 0.70677659
accuracy_optimism_corrected_CIU 0.79792542
enet_model$conf_matrices
$original
    Predicted
True   0   1
   0 262   1
   1  67  20

$czech
    Predicted
True   0   1
   0 160   1
   1  36  12

$no
    Predicted
True   0   1
   0 102   0
   1  31   8
enet_model$plot


roc_c

Saving results

models_summ_df_colon <- do.call(rbind, 
  models_summ[grep(segment,names(models_summ),value = TRUE)])

write.csv(models_summ_df_colon,file.path(path,paste0("elastic_net_",segment,".csv")))

Supplementary models

CLR-transformed data

kNN
model="knn"
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               11.0000000
auc                              0.9118701
auc_optimism_corrected           0.6193951
auc_optimism_corrected_CIL       0.5321155
auc_optimism_corrected_CIU       0.6960323
accuracy                         0.8457143
accuracy_optimism_corrected      0.7198609
accuracy_optimism_corrected_CIL  0.6159331
accuracy_optimism_corrected_CIU  0.7970677
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)


# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 1644 ASV(s)
Removing 43 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs


# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               10.0000000
auc                              0.9846862
auc_optimism_corrected           0.9336959
auc_optimism_corrected_CIL       0.9016284
auc_optimism_corrected_CIU       0.9715522
accuracy                         0.9233871
accuracy_optimism_corrected      0.8776633
accuracy_optimism_corrected_CIL  0.8257353
accuracy_optimism_corrected_CIU  0.9427339
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 527 ASV(s)
Removing 54 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               13.0000000
auc                              0.9580390
auc_optimism_corrected           0.8644098
auc_optimism_corrected_CIL       0.8002895
auc_optimism_corrected_CIU       0.9047383
accuracy                         0.9078014
accuracy_optimism_corrected      0.7857898
accuracy_optimism_corrected_CIL  0.7416603
accuracy_optimism_corrected_CIU  0.8331744
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_asv_tab,
                                                colon_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               10.0000000
auc                              0.9305537
auc_optimism_corrected           0.7628238
auc_optimism_corrected_CIL       0.6612676
auc_optimism_corrected_CIU       0.8130056
accuracy                         0.7942857
accuracy_optimism_corrected      0.7591353
accuracy_optimism_corrected_CIL  0.7089049
accuracy_optimism_corrected_CIU  0.8071954
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs


# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               12.0000000
auc                              0.9046370
auc_optimism_corrected           0.6192079
auc_optimism_corrected_CIL       0.5166357
auc_optimism_corrected_CIU       0.7782418
accuracy                         0.7771429
accuracy_optimism_corrected      0.7540616
accuracy_optimism_corrected_CIL  0.6551291
accuracy_optimism_corrected_CIU  0.8465071
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 98 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs


# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               10.0000000
auc                              0.9907546
auc_optimism_corrected           0.9111602
auc_optimism_corrected_CIL       0.8565643
auc_optimism_corrected_CIU       0.9728443
accuracy                         0.8225806
accuracy_optimism_corrected      0.8201925
accuracy_optimism_corrected_CIL  0.7343137
accuracy_optimism_corrected_CIU  0.8971792
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 39 ASV(s)
Removing 6 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs


# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               18.0000000
auc                              0.9571003
auc_optimism_corrected           0.8711618
auc_optimism_corrected_CIL       0.8101521
auc_optimism_corrected_CIU       0.9341724
accuracy                         0.7900943
accuracy_optimism_corrected      0.7208789
accuracy_optimism_corrected_CIL  0.6418008
accuracy_optimism_corrected_CIU  0.7879489
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_genus_tab,
                                                colon_genus_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
# save the results
supplements_models[["models_summ"]][["knn_model"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               11.0000000
auc                              0.8893186
auc_optimism_corrected           0.7902483
auc_optimism_corrected_CIL       0.7230248
auc_optimism_corrected_CIU       0.8497950
accuracy                         0.8085714
accuracy_optimism_corrected      0.7628243
accuracy_optimism_corrected_CIL  0.7185538
accuracy_optimism_corrected_CIU  0.8085448
roc_c

Random Forest
model="rf"
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "81"       
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.647063" 
auc_optimism_corrected_CIL      "0.5129271"
auc_optimism_corrected_CIU      "0.7859063"
accuracy                        "1"        
accuracy_optimism_corrected     "0.7630961"
accuracy_optimism_corrected_CIL "0.6697138"
accuracy_optimism_corrected_CIU "0.826758" 
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 1644 ASV(s)
Removing 43 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "399"      
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.9435052"
auc_optimism_corrected_CIL      "0.9084575"
auc_optimism_corrected_CIU      "0.9855619"
accuracy                        "1"        
accuracy_optimism_corrected     "0.839974" 
accuracy_optimism_corrected_CIL "0.7651471"
accuracy_optimism_corrected_CIU "0.9229859"
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 527 ASV(s)
Removing 54 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "105"      
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.902604" 
auc_optimism_corrected_CIL      "0.818777" 
auc_optimism_corrected_CIU      "0.9671069"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8518032"
accuracy_optimism_corrected_CIL "0.7927907"
accuracy_optimism_corrected_CIU "0.9166186"
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_asv_tab,
                                                colon_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "31"       
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.8775337"
auc_optimism_corrected_CIL      "0.837927" 
auc_optimism_corrected_CIU      "0.9428915"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8393827"
accuracy_optimism_corrected_CIL "0.8161337"
accuracy_optimism_corrected_CIU "0.8779587"
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "61"       
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.6441319"
auc_optimism_corrected_CIL      "0.5280122"
auc_optimism_corrected_CIU      "0.7594818"
accuracy                        "1"        
accuracy_optimism_corrected     "0.7511293"
accuracy_optimism_corrected_CIL "0.6591262"
accuracy_optimism_corrected_CIU "0.8142136"
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 98 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "17"       
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9609761"
auc_optimism_corrected_CIL      "0.9309369"
auc_optimism_corrected_CIU      "0.996648" 
accuracy                        "1"        
accuracy_optimism_corrected     "0.8907039"
accuracy_optimism_corrected_CIL "0.8462518"
accuracy_optimism_corrected_CIU "0.9622759"
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 39 ASV(s)
Removing 6 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "145"      
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9327948"
auc_optimism_corrected_CIL      "0.9093843"
auc_optimism_corrected_CIU      "0.9691381"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8753493"
accuracy_optimism_corrected_CIL "0.8543221"
accuracy_optimism_corrected_CIU "0.9174511"
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_genus_tab,
                                                colon_genus_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "15"       
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.8589471"
auc_optimism_corrected_CIL      "0.8065168"
auc_optimism_corrected_CIU      "0.8991119"
accuracy                        "1"        
accuracy_optimism_corrected     "0.82244"  
accuracy_optimism_corrected_CIL "0.7632796"
accuracy_optimism_corrected_CIU "0.8857639"
roc_c

Gradient boosting
model="gb"
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.6148368
auc_optimism_corrected_CIL        0.5423221
auc_optimism_corrected_CIU        0.6820819
accuracy                          1.0000000
accuracy_optimism_corrected       0.7576371
accuracy_optimism_corrected_CIL   0.6587331
accuracy_optimism_corrected_CIU   0.8067363
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 1644 ASV(s)
Removing 43 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         100.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9560002
auc_optimism_corrected_CIL        0.9315334
auc_optimism_corrected_CIU        0.9884204
accuracy                          1.0000000
accuracy_optimism_corrected       0.8506360
accuracy_optimism_corrected_CIL   0.7681373
accuracy_optimism_corrected_CIU   0.9263467
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_clr",
                                     patient = TRUE)
Removing 527 ASV(s)
Removing 54 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   30.0000000
auc                               1.0000000
auc_optimism_corrected            0.9464332
auc_optimism_corrected_CIL        0.8709877
auc_optimism_corrected_CIU        0.9805888
accuracy                          1.0000000
accuracy_optimism_corrected       0.8823593
accuracy_optimism_corrected_CIL   0.8261426
accuracy_optimism_corrected_CIU   0.9234599
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_asv_tab,
                                                colon_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.8622298
auc_optimism_corrected_CIL        0.8179067
auc_optimism_corrected_CIU        0.9279510
accuracy                          1.0000000
accuracy_optimism_corrected       0.8250690
accuracy_optimism_corrected_CIL   0.7954854
accuracy_optimism_corrected_CIU   0.8745536
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.6736680
auc_optimism_corrected_CIL        0.5915391
auc_optimism_corrected_CIU        0.7914096
accuracy                          1.0000000
accuracy_optimism_corrected       0.7602758
accuracy_optimism_corrected_CIL   0.6513808
accuracy_optimism_corrected_CIU   0.8569308
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 98 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 1.0000000
shrinkage                         0.1000000
n.minobsinnode                   20.0000000
auc                               1.0000000
auc_optimism_corrected            0.9735137
auc_optimism_corrected_CIL        0.9426804
auc_optimism_corrected_CIU        0.9927191
accuracy                          1.0000000
accuracy_optimism_corrected       0.9007885
accuracy_optimism_corrected_CIL   0.8433943
accuracy_optimism_corrected_CIU   0.9309314
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_clr",
                                     patient = TRUE)
Removing 39 ASV(s)
Removing 6 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9642380
auc_optimism_corrected_CIL        0.9495139
auc_optimism_corrected_CIU        0.9860100
accuracy                          1.0000000
accuracy_optimism_corrected       0.9142135
accuracy_optimism_corrected_CIL   0.8871296
accuracy_optimism_corrected_CIU   0.9571992
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_genus_tab,
                                                colon_genus_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_clr")
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         100.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.8240318
auc_optimism_corrected_CIL        0.7238738
auc_optimism_corrected_CIU        0.8684794
accuracy                          1.0000000
accuracy_optimism_corrected       0.8132742
accuracy_optimism_corrected_CIL   0.7509221
accuracy_optimism_corrected_CIU   0.8824551
roc_c

Relative abundances

Elastic net
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                       [,1]
alpha                           0.800000000
lambda                          0.005377316
auc                             1.000000000
auc_czech                       1.000000000
auc_no                          1.000000000
auc_optimism_corrected          0.613054927
auc_optimism_corrected_CIL      0.490857300
auc_optimism_corrected_CIU      0.723265090
accuracy                        0.997142857
accuracy_czech                          NaN
accuracy_no                     1.000000000
accuracy_optimism_corrected     0.733453765
accuracy_optimism_corrected_CIL 0.682269385
accuracy_optimism_corrected_CIU 0.798079758
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 1644 ASV(s)
Removing 43 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                       [,1]
alpha                           0.800000000
lambda                          0.003746731
auc                             1.000000000
auc_czech                       1.000000000
auc_no                          1.000000000
auc_optimism_corrected          0.960651806
auc_optimism_corrected_CIL      0.873676035
auc_optimism_corrected_CIU      0.989528910
accuracy                        1.000000000
accuracy_czech                          NaN
accuracy_no                     1.000000000
accuracy_optimism_corrected     0.895125287
accuracy_optimism_corrected_CIL 0.819362745
accuracy_optimism_corrected_CIU 0.972995169
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)


# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 527 ASV(s)
Removing 54 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.60000000
lambda                          0.01268861
auc                             1.00000000
auc_czech                       1.00000000
auc_no                          1.00000000
auc_optimism_corrected          0.92948430
auc_optimism_corrected_CIL      0.89166078
auc_optimism_corrected_CIU      0.95882539
accuracy                        1.00000000
accuracy_czech                         NaN
accuracy_no                     1.00000000
accuracy_optimism_corrected     0.86754960
accuracy_optimism_corrected_CIL 0.80839950
accuracy_optimism_corrected_CIU 0.91957237
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_asv_tab,
                                                colon_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.60000000
lambda                          0.06073667
auc                             0.88955902
auc_czech                       0.89201605
auc_no                          0.88939165
auc_optimism_corrected          0.79485800
auc_optimism_corrected_CIL      0.71658439
auc_optimism_corrected_CIU      0.85869649
accuracy                        0.80857143
accuracy_czech                         NaN
accuracy_no                     0.81560284
accuracy_optimism_corrected     0.76801287
accuracy_optimism_corrected_CIL 0.72887541
accuracy_optimism_corrected_CIU 0.81859244
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                     [,1]
alpha                           0.0000000
lambda                          0.0432959
auc                             0.9950614
auc_czech                       0.9940476
auc_no                          0.9972348
auc_optimism_corrected          0.5433647
auc_optimism_corrected_CIL      0.4248570
auc_optimism_corrected_CIU      0.6886757
accuracy                        0.9542857
accuracy_czech                        NaN
accuracy_no                     0.9503546
accuracy_optimism_corrected     0.6803041
accuracy_optimism_corrected_CIL 0.6065087
accuracy_optimism_corrected_CIU 0.7365934
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)


# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 98 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                       [,1]
alpha                           0.600000000
lambda                          0.002205278
auc                             1.000000000
auc_czech                       1.000000000
auc_no                          1.000000000
auc_optimism_corrected          0.924618301
auc_optimism_corrected_CIL      0.870002633
auc_optimism_corrected_CIU      0.976756973
accuracy                        1.000000000
accuracy_czech                          NaN
accuracy_no                     1.000000000
accuracy_optimism_corrected     0.867986390
accuracy_optimism_corrected_CIL 0.814881321
accuracy_optimism_corrected_CIU 0.919479726
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 39 ASV(s)
Removing 6 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.00000000
lambda                          0.03919916
auc                             0.99981107
auc_czech                       0.99960771
auc_no                          1.00000000
auc_optimism_corrected          0.91708414
auc_optimism_corrected_CIL      0.87732725
auc_optimism_corrected_CIU      0.95879325
accuracy                        0.99056604
accuracy_czech                         NaN
accuracy_no                     0.99404762
accuracy_optimism_corrected     0.86364351
accuracy_optimism_corrected_CIL 0.81937500
accuracy_optimism_corrected_CIU 0.90429004
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_genus_tab,
                                                colon_genus_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
enet_model <- glmnet_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(enet_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["enet_model_ra"]][[model_name]] <- enet_model$model_summary

supplements_models[["roc_cs"]][["enet_model_ra"]][[model_name]] <- enet_model$kfold_rocobjs

# see the results
enet_model$model_summary %>% t()
                                      [,1]
alpha                           0.80000000
lambda                          0.06978427
auc                             0.75075390
auc_czech                       0.73770704
auc_no                          0.74358974
auc_optimism_corrected          0.67281383
auc_optimism_corrected_CIL      0.58167543
auc_optimism_corrected_CIU      0.74475106
accuracy                        0.75714286
accuracy_czech                         NaN
accuracy_no                     0.73758865
accuracy_optimism_corrected     0.74781625
accuracy_optimism_corrected_CIL 0.69903668
accuracy_optimism_corrected_CIU 0.80869956
roc_c

kNN
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               17.0000000
auc                              0.8139067
auc_optimism_corrected           0.4438631
auc_optimism_corrected_CIL       0.3291721
auc_optimism_corrected_CIU       0.5881490
accuracy                         0.7571429
accuracy_optimism_corrected      0.6934797
accuracy_optimism_corrected_CIL  0.5889706
accuracy_optimism_corrected_CIU  0.7667208
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 1644 ASV(s)
Removing 43 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               10.0000000
auc                              0.9629114
auc_optimism_corrected           0.7843430
auc_optimism_corrected_CIL       0.6912901
auc_optimism_corrected_CIU       0.8648065
accuracy                         0.8145161
accuracy_optimism_corrected      0.7400341
accuracy_optimism_corrected_CIL  0.6227501
accuracy_optimism_corrected_CIU  0.8273529
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 527 ASV(s)
Removing 54 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               29.0000000
auc                              0.8944811
auc_optimism_corrected           0.7938669
auc_optimism_corrected_CIL       0.7349389
auc_optimism_corrected_CIU       0.8782914
accuracy                         0.8274232
accuracy_optimism_corrected      0.7413141
accuracy_optimism_corrected_CIL  0.6641102
accuracy_optimism_corrected_CIU  0.8439400
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_asv_tab,
                                                colon_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               10.0000000
auc                              0.8733884
auc_optimism_corrected           0.7140626
auc_optimism_corrected_CIL       0.6480679
auc_optimism_corrected_CIU       0.7894333
accuracy                         0.8028571
accuracy_optimism_corrected      0.7515490
accuracy_optimism_corrected_CIL  0.6955300
accuracy_optimism_corrected_CIU  0.8365275
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               11.0000000
auc                              0.9109523
auc_optimism_corrected           0.6234391
auc_optimism_corrected_CIL       0.5003192
auc_optimism_corrected_CIU       0.7414446
accuracy                         0.8000000
accuracy_optimism_corrected      0.7494729
accuracy_optimism_corrected_CIL  0.6423317
accuracy_optimism_corrected_CIU  0.8130760
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 98 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               10.0000000
auc                              0.9592704
auc_optimism_corrected           0.7557076
auc_optimism_corrected_CIL       0.6161263
auc_optimism_corrected_CIU       0.8674111
accuracy                         0.7620968
accuracy_optimism_corrected      0.7306721
accuracy_optimism_corrected_CIL  0.6425903
accuracy_optimism_corrected_CIU  0.7947059
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 39 ASV(s)
Removing 6 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary

supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               11.0000000
auc                              0.9436270
auc_optimism_corrected           0.8396098
auc_optimism_corrected_CIL       0.7714357
auc_optimism_corrected_CIU       0.8993877
accuracy                         0.8773585
accuracy_optimism_corrected      0.7730456
accuracy_optimism_corrected_CIL  0.7068539
accuracy_optimism_corrected_CIU  0.8297749
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_genus_tab,
                                                colon_genus_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
knn_model <- knn_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(knn_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
# save the results
supplements_models[["models_summ"]][["knn_model_ra"]][[model_name]] <- knn_model$model_summary
supplements_models[["roc_cs"]][["knn_model_ra"]][[model_name]] <- knn_model$kfold_rocobjs

# see the results
knn_model$model_summary %>% t()
                                      [,1]
k                               16.0000000
auc                              0.7672960
auc_optimism_corrected           0.6409962
auc_optimism_corrected_CIL       0.5269546
auc_optimism_corrected_CIU       0.7463867
accuracy                         0.7657143
accuracy_optimism_corrected      0.7423961
accuracy_optimism_corrected_CIL  0.7085608
accuracy_optimism_corrected_CIU  0.7772584
roc_c

Random Forest
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "245"      
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.6648962"
auc_optimism_corrected_CIL      "0.5579935"
auc_optimism_corrected_CIU      "0.7732615"
accuracy                        "1"        
accuracy_optimism_corrected     "0.7906038"
accuracy_optimism_corrected_CIL "0.7181079"
accuracy_optimism_corrected_CIU "0.8579319"
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 1644 ASV(s)
Removing 43 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "47"       
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9709215"
auc_optimism_corrected_CIL      "0.9461604"
auc_optimism_corrected_CIU      "0.9992061"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8739657"
accuracy_optimism_corrected_CIL "0.8207317"
accuracy_optimism_corrected_CIU "0.9642048"
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 527 ASV(s)
Removing 54 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "39"       
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9434682"
auc_optimism_corrected_CIL      "0.9109581"
auc_optimism_corrected_CIU      "0.968517" 
accuracy                        "1"        
accuracy_optimism_corrected     "0.8756203"
accuracy_optimism_corrected_CIL "0.8261426"
accuracy_optimism_corrected_CIU "0.9348684"
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_asv_tab,
                                                colon_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "7"        
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.892496" 
auc_optimism_corrected_CIL      "0.8406943"
auc_optimism_corrected_CIU      "0.9559446"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8395267"
accuracy_optimism_corrected_CIL "0.799001" 
accuracy_optimism_corrected_CIU "0.877986" 
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "61"       
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.6592904"
auc_optimism_corrected_CIL      "0.5159226"
auc_optimism_corrected_CIU      "0.8034246"
accuracy                        "1"        
accuracy_optimism_corrected     "0.751142" 
accuracy_optimism_corrected_CIL "0.637694" 
accuracy_optimism_corrected_CIU "0.8387735"
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 98 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "49"       
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9665928"
auc_optimism_corrected_CIL      "0.9402272"
auc_optimism_corrected_CIU      "0.9911378"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8922367"
accuracy_optimism_corrected_CIL "0.8499717"
accuracy_optimism_corrected_CIU "0.9318095"
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 39 ASV(s)
Removing 6 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                        clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary

supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs


# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "61"       
splitrule                       "gini"     
min.node.size                   "5"        
auc                             "1"        
auc_optimism_corrected          "0.9434458"
auc_optimism_corrected_CIL      "0.9158285"
auc_optimism_corrected_CIU      "0.9854407"
accuracy                        "1"        
accuracy_optimism_corrected     "0.8839496"
accuracy_optimism_corrected_CIL "0.8487472"
accuracy_optimism_corrected_CIU "0.919606" 
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_genus_tab,
                                                colon_genus_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
rf_model <- rf_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(rf_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["rf_model_ra"]][[model_name]] <- rf_model$model_summary
supplements_models[["roc_cs"]][["rf_model_ra"]][[model_name]] <- rf_model$kfold_rocobjs

# see the results
rf_model$model_summary %>% t()
                                [,1]       
mtry                            "31"       
splitrule                       "gini"     
min.node.size                   "2"        
auc                             "1"        
auc_optimism_corrected          "0.8495906"
auc_optimism_corrected_CIL      "0.7950936"
auc_optimism_corrected_CIU      "0.8966604"
accuracy                        "1"        
accuracy_optimism_corrected     "0.825695" 
accuracy_optimism_corrected_CIL "0.7573706"
accuracy_optimism_corrected_CIU "0.8824551"
roc_c

Gradient boosting
ASV level
level="ASV"

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.6240362
auc_optimism_corrected_CIL        0.5222934
auc_optimism_corrected_CIU        0.7546738
accuracy                          1.0000000
accuracy_optimism_corrected       0.7661990
accuracy_optimism_corrected_CIL   0.7053971
accuracy_optimism_corrected_CIU   0.8279869
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 1644 ASV(s)
Removing 43 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9706600
auc_optimism_corrected_CIL        0.9444854
auc_optimism_corrected_CIU        0.9970412
accuracy                          1.0000000
accuracy_optimism_corrected       0.8940968
accuracy_optimism_corrected_CIL   0.8323888
accuracy_optimism_corrected_CIU   0.9670908
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_asv_tab,
                                     colon_taxa_tab,
                                     colon_metadata,
                                     group, usage="ml_ra",
                                     patient = TRUE)
Removing 527 ASV(s)
Removing 54 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   30.0000000
auc                               1.0000000
auc_optimism_corrected            0.9537613
auc_optimism_corrected_CIL        0.9083638
auc_optimism_corrected_CIU        0.9737677
accuracy                          1.0000000
accuracy_optimism_corrected       0.8841500
accuracy_optimism_corrected_CIL   0.8117410
accuracy_optimism_corrected_CIU   0.9152636
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_asv_tab,
                                                colon_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 1358 ASV(s)
Removing 17 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.8681106
auc_optimism_corrected_CIL        0.7814398
auc_optimism_corrected_CIU        0.9406792
accuracy                          1.0000000
accuracy_optimism_corrected       0.8298620
accuracy_optimism_corrected_CIL   0.7655238
accuracy_optimism_corrected_CIU   0.9041700
roc_c

Genus level
level="genus"

Aggregate taxa

genus_data <- aggregate_taxa(colon_asv_tab,
                             colon_taxa_tab,
                             taxonomic_level = level)

colon_genus_tab <- genus_data[[1]]
colon_genus_taxa_tab <- genus_data[[2]]

rPSC vs non-rPSC

group <- c("rPSC","non-rPSC")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.6462040
auc_optimism_corrected_CIL        0.5751847
auc_optimism_corrected_CIU        0.7875026
accuracy                          1.0000000
accuracy_optimism_corrected       0.7712399
accuracy_optimism_corrected_CIL   0.6992055
accuracy_optimism_corrected_CIU   0.8481626
roc_c

rPSC vs healthy

group <- c("rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 98 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 3.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9824653
auc_optimism_corrected_CIL        0.9736756
auc_optimism_corrected_CIU        0.9971742
accuracy                          1.0000000
accuracy_optimism_corrected       0.9155915
accuracy_optimism_corrected_CIL   0.8790172
accuracy_optimism_corrected_CIU   0.9439629
roc_c

non-rPSC vs healthy

group <- c("non-rPSC","healthy")
comparison_name <- paste0(group[1], " vs ",group[2])
model_name <- paste(comparison_name,level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep(colon_genus_tab,
                                     colon_genus_taxa_tab,
                                     colon_metadata,
                                     group, 
                                     usage="ml_ra",
                                     patient = TRUE)
Removing 39 ASV(s)
Removing 6 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                          clust_var="Patient",
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary

supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs

# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         200.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.9664948
auc_optimism_corrected_CIL        0.9412675
auc_optimism_corrected_CIU        0.9824918
accuracy                          1.0000000
accuracy_optimism_corrected       0.9126731
accuracy_optimism_corrected_CIL   0.8841197
accuracy_optimism_corrected_CIU   0.9393719
roc_c

rPSC effect

model_name <- paste("rPSC effect",level,segment)

# prepare the data
filt_colon_uni_data <- binomial_prep_psc_effect(colon_genus_tab,
                                                colon_genus_taxa_tab, 
                                                colon_metadata,
                                                rpsc_effect[[paste(segment,level)]],
                                                usage="ml_ra")
Removing 28 ASV(s)
Removing 5 ASV(s)
# fit the model
gbm_model <- gbm_binomial(filt_colon_uni_data,
                              sample_method = "atypboot",
                              outcome="Group", 
                              N=10,
                              reuse=TRUE,
                              file=model_name,
                              Q="Q2")

# ROC curve
roc_c <- roc_curve(gbm_model, group)
Warning: Ignoring unknown aesthetics: by
# save the results
supplements_models[["models_summ"]][["gbm_model_ra"]][[model_name]] <- gbm_model$model_summary
supplements_models[["roc_cs"]][["gbm_model_ra"]][[model_name]] <- gbm_model$kfold_rocobjs


# see the results
gbm_model$model_summary %>% t()
                                       [,1]
n.trees                         500.0000000
interaction.depth                 5.0000000
shrinkage                         0.1000000
n.minobsinnode                   10.0000000
auc                               1.0000000
auc_optimism_corrected            0.8236631
auc_optimism_corrected_CIL        0.7353234
auc_optimism_corrected_CIU        0.8705153
accuracy                          1.0000000
accuracy_optimism_corrected       0.8177658
accuracy_optimism_corrected_CIL   0.7556128
accuracy_optimism_corrected_CIU   0.8545296
roc_c

Saving results

models_list <- list()

for (model_name in names(supplements_models$models_summ)){
  df <- do.call(rbind, supplements_models$models_summ[[model_name]])
  models_list[[model_name]] <- df
}

write.xlsx(models_list,
           file=file.path(path,paste0("supplements_models_",segment,".xlsx")),
           rowNames=TRUE)

Results overview

Alpha diversity

pc_observed[[segment]]
pc_shannon[[segment]]
pc_simpson[[segment]]
pc_pielou[[segment]]

Plots

alpha_div_plots[[paste(segment,"Country")]]

alpha_div_plots[[paste(segment,"Custom")]]

Beta diversity

Main results

pairwise_aitchison_raw[[paste("genus", segment)]]

PCA

pca_plots_list[[paste(segment,"genus custom")]]

Supplements

knitr::kable(supplements_beta[!grepl("PCoA",names(supplements_beta))],
             digits = 3,
             caption = "Supplementary PERMANOVA results")
Supplementary PERMANOVA results
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.251 1.208 0.008 0.241 0.241
rPSC vs healthy 1 0.813 4.432 0.039 0.001 0.002 **
non-rPSC vs healthy 1 1.241 6.538 0.034 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1.449 6.976 0.049 0.001 0.001 ***
rPSC vs healthy , Country 1 0.972 5.300 0.047 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.336 7.038 0.037 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.151 0.724 0.005 0.803 0.803
rPSC vs healthy : Country 1 0.287 1.572 0.014 0.067 0.100
non-rPSC vs healthy : Country 1 0.354 1.873 0.010 0.011 0.033 *
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.337 1.138 0.008 0.241 0.241
rPSC vs healthy 1 0.887 3.269 0.030 0.001 0.002 **
non-rPSC vs healthy 1 1.349 4.846 0.026 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1.460 4.927 0.035 0.001 0.001 ***
rPSC vs healthy , Country 1 1.092 4.023 0.036 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.476 5.300 0.029 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.242 0.817 0.006 0.823 0.823
rPSC vs healthy : Country 1 0.342 1.261 0.011 0.118 0.177
non-rPSC vs healthy : Country 1 0.445 1.604 0.009 0.014 0.042 *
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 316.296 1.176 0.008 0.071 0.071
rPSC vs healthy 1 830.867 2.897 0.027 0.001 0.002 **
non-rPSC vs healthy 1 1156.137 4.137 0.023 0.001 0.002 **
rPSC vs non-rPSC , Country 1 639.519 2.378 0.017 0.001 0.001 ***
rPSC vs healthy , Country 1 598.496 2.087 0.019 0.001 0.001 ***
non-rPSC vs healthy , Country 1 752.840 2.694 0.015 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 222.179 0.825 0.006 0.960 0.960
rPSC vs healthy : Country 1 262.783 0.916 0.008 0.746 0.960
non-rPSC vs healthy : Country 1 291.928 1.045 0.006 0.333 0.960
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.505 1.557 0.011 0.026 0.026 *
rPSC vs healthy 1 1.342 4.364 0.039 0.001 0.002 **
non-rPSC vs healthy 1 1.979 6.424 0.034 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1.444 4.451 0.032 0.001 0.001 ***
rPSC vs healthy , Country 1 1.059 3.444 0.031 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.394 4.525 0.024 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.333 1.027 0.007 0.386 0.386
rPSC vs healthy : Country 1 0.390 1.272 0.011 0.093 0.140
non-rPSC vs healthy : Country 1 0.447 1.456 0.008 0.036 0.108
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.518 1.318 0.009 0.029 0.029 *
rPSC vs healthy 1 1.117 2.934 0.027 0.001 0.002 **
non-rPSC vs healthy 1 1.607 4.216 0.023 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1.214 3.089 0.022 0.001 0.001 ***
rPSC vs healthy , Country 1 0.939 2.467 0.023 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1.203 3.157 0.017 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.390 0.992 0.007 0.469 0.469
rPSC vs healthy : Country 1 0.430 1.130 0.010 0.131 0.196
non-rPSC vs healthy : Country 1 0.501 1.318 0.007 0.026 0.078
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.504 2.488 0.007 0.267 0.267
rPSC vs healthy 1 2.464 13.675 0.051 0.001 0.002 **
non-rPSC vs healthy 1 3.227 18.295 0.039 0.001 0.002 **
rPSC vs non-rPSC , Country 1 5.037 24.881 0.066 0.001 0.001 ***
rPSC vs healthy , Country 1 2.136 11.852 0.044 0.001 0.001 ***
non-rPSC vs healthy , Country 1 4.670 26.476 0.057 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.446 2.209 0.006 0.460 0.460
rPSC vs healthy : Country 1 0.495 2.765 0.010 0.102 0.153
non-rPSC vs healthy : Country 1 1.025 5.881 0.012 0.001 0.003 **
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.590 2.035 0.006 0.594 0.594
rPSC vs healthy 1 2.438 9.075 0.035 0.001 0.002 **
non-rPSC vs healthy 1 3.380 12.658 0.028 0.001 0.002 **
rPSC vs non-rPSC , Country 1 4.994 17.225 0.047 0.001 0.001 ***
rPSC vs healthy , Country 1 2.338 8.704 0.033 0.001 0.001 ***
non-rPSC vs healthy , Country 1 4.864 18.215 0.040 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.589 2.039 0.006 0.696 0.696
rPSC vs healthy : Country 1 0.632 2.365 0.009 0.208 0.312
non-rPSC vs healthy : Country 1 1.174 4.433 0.010 0.001 0.003 **
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 470.424 1.893 0.005 0.968 0.968
rPSC vs healthy 1 1842.677 6.979 0.027 0.001 0.002 **
non-rPSC vs healthy 1 2475.754 9.500 0.022 0.001 0.002 **
rPSC vs non-rPSC , Country 1 1644.116 6.616 0.019 0.001 0.001 ***
rPSC vs healthy , Country 1 1119.321 4.239 0.017 0.001 0.001 ***
non-rPSC vs healthy , Country 1 1833.401 7.035 0.016 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 470.881 1.900 0.005 0.989 0.989
rPSC vs healthy : Country 1 517.888 1.969 0.008 0.896 0.989
non-rPSC vs healthy : Country 1 611.799 2.355 0.005 0.163 0.489
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.737 2.327 0.006 0.415 0.415
rPSC vs healthy 1 3.308 10.870 0.041 0.001 0.002 **
non-rPSC vs healthy 1 4.794 16.082 0.036 0.001 0.002 **
rPSC vs non-rPSC , Country 1 4.600 14.526 0.040 0.001 0.001 ***
rPSC vs healthy , Country 1 2.184 7.177 0.027 0.001 0.001 ***
non-rPSC vs healthy , Country 1 4.330 14.527 0.032 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.792 2.512 0.007 0.383 0.383
rPSC vs healthy : Country 1 0.815 2.697 0.010 0.145 0.217
non-rPSC vs healthy : Country 1 1.360 4.601 0.010 0.002 0.006 **
pairs Df SumsOfSqs F.Model R2 p.value p.adjusted sig
rPSC vs non-rPSC 1 0.737 1.909 0.005 0.873 0.873
rPSC vs healthy 1 2.563 6.794 0.026 0.001 0.002 **
non-rPSC vs healthy 1 3.757 10.047 0.023 0.001 0.002 **
rPSC vs non-rPSC , Country 1 3.698 9.578 0.027 0.001 0.001 ***
rPSC vs healthy , Country 1 1.887 5.001 0.019 0.001 0.001 ***
non-rPSC vs healthy , Country 1 3.508 9.381 0.021 0.001 0.001 ***
rPSC vs non-rPSC : Country 1 0.814 2.115 0.006 0.822 0.822
rPSC vs healthy : Country 1 0.853 2.271 0.009 0.388 0.582
non-rPSC vs healthy : Country 1 1.296 3.486 0.008 0.002 0.006 **

PCA

plot_list <- supplements_beta[grepl("PCoA",names(supplements_beta)) &
                              grepl(segment,names(supplements_beta))]

ggarrange(plotlist = plot_list,
          labels=names(plot_list),
          font.label = list(size=5,face="plain"),
          ncol=2,nrow=3)

Univariate analysis

Number of significant taxa

knitr::kable(cbind(as.data.frame(lapply(list_intersections,nrow)),
      as.data.frame(lapply(rpsc_effect,nrow))) %>% t() %>% 
  `colnames<-`("Count") %>% 
  `rownames<-`(c(names(list_intersections),"rPSC effect ASV","rPSC effect Genus","rPSC effect Phylum")),caption="Number of significant taxa")
Number of significant taxa
Count
colon genus non-rPSC vs rPSC 0
colon genus healthy vs rPSC 56
colon genus healthy vs non-rPSC 30
colon ASV non-rPSC vs rPSC 0
colon ASV healthy vs rPSC 98
colon ASV healthy vs non-rPSC 81
colon phylum non-rPSC vs rPSC 1
colon phylum healthy vs rPSC 5
colon phylum healthy vs non-rPSC 4
rPSC effect ASV 31
rPSC effect Genus 47
rPSC effect Phylum 2

Counts

# univar_list <- univariate_statistics(list_intersections,
#                                      psc_effect,
#                                      ileum_genus_asv_taxa_tab)
# 
# univar_df <- univar_list[[1]]
# wb <- univar_list[[2]]
# 
# # save the results
# saveWorkbook(wb,"results/Q1/DAA_final_terminal_ileum.xlsx", overwrite = TRUE)
# 
# # see the results
# univar_df

Machine learning

Main models

Summary

knitr::kable(models_summ_df_colon %>% dplyr::select(
"alpha","lambda",
"auc_optimism_corrected",
"auc_optimism_corrected_CIL",
"auc_optimism_corrected_CIU"),
             digits=3,caption="Elastic net results")
Elastic net results
alpha lambda auc_optimism_corrected auc_optimism_corrected_CIL auc_optimism_corrected_CIU
rPSC vs non-rPSC ASV colon 0.2 0.026 0.689 0.582 0.796
rPSC vs healthy ASV colon 0.8 0.005 0.984 0.964 0.999
non-rPSC vs healthy ASV colon 0.6 0.005 0.956 0.923 0.979
rPSC effect ASV colon 0.8 0.022 0.789 0.705 0.844
rPSC vs non-rPSC genus colon 0.0 0.036 0.616 0.530 0.734
rPSC vs healthy genus colon 0.8 0.000 0.958 0.911 0.997
non-rPSC vs healthy genus colon 0.2 0.003 0.964 0.942 0.987
rPSC effect genus colon 0.6 0.054 0.744 0.708 0.771

ROC - ASV level

roc_curve_all_custom(roc_cs[c(9:12)], 
                     Q="Q2",
                     model_name="enet_model")
[1] "rPSC vs non-rPSC ASV colon"    "rPSC vs healthy ASV colon"    
[3] "non-rPSC vs healthy ASV colon" "rPSC effect ASV colon"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values

ROC - Genus level

roc_curve_all_custom(roc_cs[c(13:16)],Q="Q2",
                     model_name="enet_model")
[1] "rPSC vs non-rPSC genus colon"    "rPSC vs healthy genus colon"    
[3] "non-rPSC vs healthy genus colon" "rPSC effect genus colon"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values

Supplementary models

Summary

# Build final dataframe
models_list[["enet_model"]] <- rbind(models_summ_df_ileum,models_summ_df_colon)
final_df <- tibble(row_names = rownames(models_list[[1]]))

# Loop through models and extract required values
for (model_name in names(models_list)) {
  model_df <- models_list[[model_name]]
  
  # Combine AUC_optimism_corrected with its CI values
  final_df[[model_name]] <- paste0(
    round(model_df$auc_optimism_corrected, 3), 
    " (", round(model_df$auc_optimism_corrected_CIL, 3), "; ", 
    round(model_df$auc_optimism_corrected_CIU, 3), ")"
  )
}

knitr::kable(final_df, caption="All models")
All models
row_names knn_model rf_model gbm_model enet_model_ra knn_model_ra rf_model_ra gbm_model_ra enet_model
rPSC vs non-rPSC ASV terminal_ileum 0.569 (0.377; 0.699) 0.585 (0.498; 0.667) 0.517 (0.402; 0.612) 0.6 (0.5; 0.779) 0.436 (0.344; 0.606) 0.629 (0.544; 0.752) 0.507 (0.406; 0.599) 0.593 (0.477; 0.697)
rPSC vs healthy ASV terminal_ileum 0.89 (0.82; 0.947) 0.921 (0.794; 0.973) 0.918 (0.854; 0.957) 0.953 (0.888; 0.989) 0.738 (0.585; 0.891) 0.94 (0.868; 0.992) 0.95 (0.915; 0.961) 0.957 (0.896; 0.986)
non-rPSC vs healthy ASV terminal_ileum 0.843 (0.763; 0.918) 0.876 (0.809; 0.959) 0.918 (0.879; 0.976) 0.906 (0.829; 0.958) 0.796 (0.732; 0.894) 0.909 (0.861; 0.963) 0.922 (0.862; 0.984) 0.936 (0.864; 0.978)
rPSC effect ASV terminal_ileum 0.637 (0.514; 0.758) 0.551 (0.342; 0.686) 0.609 (0.484; 0.671) 0.569 (0.475; 0.665) 0.601 (0.458; 0.708) 0.635 (0.554; 0.712) 0.639 (0.589; 0.71) 0.655 (0.52; 0.767)
rPSC vs non-rPSC genus terminal_ileum 0.477 (0.367; 0.576) 0.604 (0.455; 0.679) 0.534 (0.437; 0.666) 0.59 (0.453; 0.747) 0.525 (0.45; 0.625) 0.634 (0.561; 0.742) 0.449 (0.361; 0.541) 0.539 (0.426; 0.635)
rPSC vs healthy genus terminal_ileum 0.879 (0.724; 0.973) 0.941 (0.859; 0.982) 0.941 (0.878; 0.985) 0.852 (0.665; 0.943) 0.728 (0.564; 0.872) 0.95 (0.872; 0.994) 0.927 (0.861; 0.987) 0.924 (0.8; 0.982)
non-rPSC vs healthy genus terminal_ileum 0.902 (0.855; 0.949) 0.903 (0.83; 0.964) 0.923 (0.874; 0.966) 0.909 (0.836; 0.96) 0.827 (0.722; 0.889) 0.93 (0.866; 0.984) 0.952 (0.9; 0.995) 0.946 (0.872; 0.982)
rPSC effect genus terminal_ileum 0.581 (0.476; 0.734) 0.599 (0.528; 0.661) 0.608 (0.446; 0.754) 0.536 (0.455; 0.682) 0.546 (0.386; 0.653) 0.616 (0.551; 0.711) 0.615 (0.509; 0.777) 0.673 (0.604; 0.743)
rPSC vs non-rPSC ASV colon 0.619 (0.532; 0.696) 0.647 (0.513; 0.786) 0.615 (0.542; 0.682) 0.613 (0.491; 0.723) 0.444 (0.329; 0.588) 0.665 (0.558; 0.773) 0.624 (0.522; 0.755) 0.689 (0.582; 0.796)
rPSC vs healthy ASV colon 0.934 (0.902; 0.972) 0.944 (0.908; 0.986) 0.956 (0.932; 0.988) 0.961 (0.874; 0.99) 0.784 (0.691; 0.865) 0.971 (0.946; 0.999) 0.971 (0.944; 0.997) 0.984 (0.964; 0.999)
non-rPSC vs healthy ASV colon 0.864 (0.8; 0.905) 0.903 (0.819; 0.967) 0.946 (0.871; 0.981) 0.929 (0.892; 0.959) 0.794 (0.735; 0.878) 0.943 (0.911; 0.969) 0.954 (0.908; 0.974) 0.956 (0.923; 0.979)
rPSC effect ASV colon 0.763 (0.661; 0.813) 0.878 (0.838; 0.943) 0.862 (0.818; 0.928) 0.795 (0.717; 0.859) 0.714 (0.648; 0.789) 0.892 (0.841; 0.956) 0.868 (0.781; 0.941) 0.789 (0.705; 0.844)
rPSC vs non-rPSC genus colon 0.619 (0.517; 0.778) 0.644 (0.528; 0.759) 0.674 (0.592; 0.791) 0.543 (0.425; 0.689) 0.623 (0.5; 0.741) 0.659 (0.516; 0.803) 0.646 (0.575; 0.788) 0.616 (0.53; 0.734)
rPSC vs healthy genus colon 0.911 (0.857; 0.973) 0.961 (0.931; 0.997) 0.974 (0.943; 0.993) 0.925 (0.87; 0.977) 0.756 (0.616; 0.867) 0.967 (0.94; 0.991) 0.982 (0.974; 0.997) 0.958 (0.911; 0.997)
non-rPSC vs healthy genus colon 0.871 (0.81; 0.934) 0.933 (0.909; 0.969) 0.964 (0.95; 0.986) 0.917 (0.877; 0.959) 0.84 (0.771; 0.899) 0.943 (0.916; 0.985) 0.966 (0.941; 0.982) 0.964 (0.942; 0.987)
rPSC effect genus colon 0.79 (0.723; 0.85) 0.859 (0.807; 0.899) 0.824 (0.724; 0.868) 0.673 (0.582; 0.745) 0.641 (0.527; 0.746) 0.85 (0.795; 0.897) 0.824 (0.735; 0.871) 0.744 (0.708; 0.771)
write.csv(final_df,file=file.path(path,"AUC_all_models.csv"),row.names = FALSE)

ROC - ASV

rocs_list <- supplements_models$roc_cs
rocs_list[["enet_model"]] <- roc_cs

plot_list <- list()

for (model_name in names(rocs_list)) {
  plot_list[[model_name]] <- roc_curve_all_custom(rocs_list[[model_name]][c(1:4)],
                       Q="Q2",
                       model_name=model_name)
}
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC ASV terminal_ileum"   
[2] "rPSC vs healthy ASV terminal_ileum"    
[3] "non-rPSC vs healthy ASV terminal_ileum"
[4] "rPSC effect ASV terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
ggarrange(plotlist = plot_list,labels = names(rocs_list),font.label = list(face="plain",size=7))

ROC - genus

plot_list <- list()

for (model_name in names(rocs_list)) {
  plot_list[[model_name]] <- roc_curve_all_custom(rocs_list[[model_name]][c(5:8)],
                       Q="Q2",
                       model_name=model_name)
}
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
p <- ggarrange(plotlist = plot_list,labels = names(rocs_list),font.label = list(face="plain",size=7))
pdf("../figures/Q2/models_colon.pdf",
    height =10,width = 10)
p
dev.off()

Paper-ready visualizations

Alpha diversity

p_A <- alpha_div_plots$`terminal_ileum Country` +
  ggtitle("Terminal ileum")+
  theme(plot.title = element_text(hjust=0.5,face = "bold",size = 15)) 

p_B <-  alpha_div_plots$`colon Country` +
  ggtitle("Colon") +
  theme(plot.title = element_text(hjust=0.5,face = "bold",size = 15)) 

Q2_alpha <- ggarrange(p_A,ggplot() + theme_minimal(),p_B,nrow=1, ncol=3,
                      widths = c(1,0.1,1))
Q2_alpha

Beta diversity

pca_ti <- pca_plots_list$`terminal_ileum genus custom` 
pca_colon <- pca_plots_list$`colon genus custom` 

genus_Q2_beta <- ggarrange(pca_ti,
                           ggplot() + theme_minimal(),
                           pca_colon,ncol=3,
                           widths = c(1,0.1,1))
genus_Q2_beta

Alpha + Beta diversity

alpha_beta <- ggarrange(Q2_alpha,genus_Q2_beta,
                        ncol = 1,nrow=2,labels = c("A","B"))
alpha_beta

Elastic net

Genus level

models_to_plot <- c("knn_model","rf_model","gbm_model","enet_model")
names(models_to_plot) <- c("kNN","RF","GBoost","ENet")

# ILEUM
plot_list_ileum <- list()
for (model_name in models_to_plot) {
  plot_list_ileum[[model_name]] <- 
    roc_curve_all_custom(rocs_list[[model_name]][c(5:8)],
                       Q="Q2",
                       model_name=model_name,legend = FALSE) + 
    ggtitle(names(models_to_plot)[which(model_name==models_to_plot)]) + 
    theme(plot.title = element_text(face = "bold",size = 8)) 
}
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus terminal_ileum"   
[2] "rPSC vs healthy genus terminal_ileum"    
[3] "non-rPSC vs healthy genus terminal_ileum"
[4] "rPSC effect genus terminal_ileum"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
roc_curve_ti <- ggarrange(plotlist = plot_list_ileum)

# COLON

plot_list_colon <- list()
for (model_name in models_to_plot) {
  plot_list_colon[[model_name]] <- 
    roc_curve_all_custom(rocs_list[[model_name]][c(13:16)],
                       Q="Q2",
                       model_name=model_name,legend = FALSE) + 
    ggtitle(names(models_to_plot)[which(model_name==models_to_plot)]) + 
    theme(plot.title = element_text(face = "bold",size = 8))  
}
[1] "rPSC vs non-rPSC genus colon"    "rPSC vs healthy genus colon"    
[3] "non-rPSC vs healthy genus colon" "rPSC effect genus colon"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus colon"    "rPSC vs healthy genus colon"    
[3] "non-rPSC vs healthy genus colon" "rPSC effect genus colon"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus colon"    "rPSC vs healthy genus colon"    
[3] "non-rPSC vs healthy genus colon" "rPSC effect genus colon"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
[1] "rPSC vs non-rPSC genus colon"    "rPSC vs healthy genus colon"    
[3] "non-rPSC vs healthy genus colon" "rPSC effect genus colon"        
Warning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' valuesWarning: collapsing to unique 'x' values
roc_curve_colon <- ggarrange(plotlist = plot_list_colon)


roc_curve_plot <- ggarrange(roc_curve_ti,
                            ggplot() + theme_minimal(),
                            roc_curve_colon,
                            ggplot() + theme_minimal(),
                            ncol=4, widths = c(1,0.1,1,0.1))
roc_curve_plot

alpha_beta_elastic <- ggarrange(Q2_alpha,genus_Q2_beta,roc_curve_plot,
                        ncol = 1,nrow=3,labels = LETTERS,heights = c(1,1,1.2))
alpha_beta_elastic

pdf("../figures/Q2/FIGURE4.pdf",paper = "a4",height = 10,width = 10)
alpha_beta_elastic
dev.off()

Dot heatmap - DAA

p_ileum <- dot_heatmap_ileum + 
  ggtitle("Terminal ileum") +
  theme(plot.title = element_text(hjust=0.5,face = "bold",size = 15),
        legend.position = "none")


p_colon <- dot_heatmap_colon  +
  ggtitle("Colon") +
  theme(plot.title = element_text(hjust=0.5,face = "bold",size = 15),
        legend.position = "none")

heatmap_plot <- ggarrange(p_ileum,
                          p_colon,
                          ncol = 2)
heatmap_plot

pdf("../figures/Q2/FIGURE5.pdf",
    height =10,width = 8,paper="a4")
heatmap_plot
dev.off()

Session info

LS0tDQp0aXRsZTogIlBTQyBhcnRpY2xlIGFuYWx5c2lzIFEyIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyBDdXN0b20gRnVuY3Rpb25zDQoNCg0KYGBge3J9DQpzb3VyY2UoImN1c3RvbV9mdW5jdGlvbnMuUiIpDQpgYGANCg0KDQojIDIuIEh5cG90aGVzaXM6IDIuIFBTQyByZWN1cnJlbmNlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIHNwZWNpZmljIGNvbXBvc2l0aW9uIG9mIHRoZSBndXQgbWljcm9iaW9tZQ0KDQoqKnJQU0MgdnMgbm9uLXJQU0MgdnMgSGVhbHRoeSBhbmFseXNpcyBvbiBtZXJnZWQgZGF0YSoqDQoNCi0gICBBbHBoYSBkaXZlcnNpdHkg4oCTXD4gZ3JvdXAgZWZmZWN0LCBjb3VudHJ5IGVmZmVjdCwgaW50ZXJhY3Rpb24gZWZmZWN0DQoNCi0gICBCZXRhIGRpdmVyc2l0eSDigJMgUEVSTUFOT1ZBLCBQQ0EgLVw+IGdyb3VwIGVmZmVjdCwgY291bnRyeSBlZmZlY3QsDQogICAgaW50ZXJhY3Rpb24gZWZmZWN0DQoNCi0gICBEQUEgLVw+DQoNCiAgICAtICAgR3JvdXAgZWZmZWN0IOKAkyBsaW5EQSArIE1hQXNMaW4yIGludGVyc2VjdGlvbg0KDQogICAgLSAgIENvdW50cnkgZWZmZWN0IOKAkyBsaW5EQSArIE1hQXNMaW4yIHVuaW9uDQoNCioqclBTQyB2cyBub24tclBTQyoqIOKAk2J5IHRoaXMgY29tcGFyaXNvbiwgd2Ugd2lsbCBmaW5kIHRoZSBlZmZlY3Qgb2YNCnJlY3VycmVuY2UgKHdoZXRoZXIgdGhlIG1pY3JvYmlhbCBjb21wb3NpdGlvbiBpcyBhc3NvY2lhdGVkIHdpdGggaXQpDQoNCioqbm9uLXJQU0MgdnMgSGVhbHRoeSoqIOKAkyBieSB0aGlzIGNvbXBhcmlzb24sIHdlIHdpbGwgZmluZCBpZiB0aGUNCm5vbi1yUFNDIHNhbXBsZXMgYXJlIOKAnmNsb3NlcuKAnCB0byB0aGUgaGVhbHRoeSBzYW1wbGVzIHRoZW4gclBTQyBzYW1wbGVzDQppbiB0ZXJtcyBvZiB0aGUgbWljcm9iaWFsIGNvbXBvc2l0aW9uLiBJbiBvdGhlciB3b3JkcywgZG9lcyBub24tclBTQw0Kc2FtcGxlcyBoYXZlIOKAnmhlYWx0aHkgbWljcm9iaW9tZeKAnD8NCg0KKipyUFNDIHZzIEhlYWx0aHkqKiDigJMgYnkgdGhpcyBjb21wYXJpc29uLCB3ZSB3aWxsIGZpbmQgaG93IG11Y2ggYXJlIHRoZQ0KclBTQyBzYW1wbGVzIGRpZmZlcmVudCBmcm9tIGhlYWx0aHkgc2FtcGxlcy4NCg0KSG93ZXZlciwgdGhlIHJQU0MgYW5kIG5vbi1yUFNDIHNhbXBsZXMgYXJlIG5vdCBkaWZmZXJlbnQgYXQgYWxsIChzZWUNCnJlc3VsdHMpLiBUaGVyZWZvcmUsIHdlIGNhbiBkbyBFWENMVVNJVkUgTEVGVCBKT0lOIG9mIGRpZmZlcmVudGlhbGx5DQphYnVuZGFudCB0YXhhIGZyb20gdGhlIGFuYWx5c2VzIChyUFNDIHZzIEhlYWx0aHksIG5vbi1yUFNDIHZzIEhlYWx0aHkpDQoNCg0KIyMgRGF0YSBJbXBvcnQNCg0KSW1wb3J0aW5nIEFTViwgdGF4YSBhbmQgbWV0YWRhdGEgdGFibGVzIGZvciBib3RoIGN6ZWNoIGFuZCBub3J3YXkNCnNhbXBsZXMuDQoNCiMgRGF0YSBJbXBvcnQNCg0KSW1wb3J0aW5nIEFTViwgdGF4YSBhbmQgbWV0YWRhdGEgdGFibGVzIGZvciBib3RoIEN6ZWNoIGFuZCBOb3J3YXkNCnNhbXBsZXMuDQoNCioqQ3plY2gqKg0KDQpgYGB7cn0NCnBhdGggPSAiLi4vLi4vZGF0YS9hbmFseXNpc19yZWFkeV9kYXRhL2lrZW0vIg0KYXN2X3RhYl9pa2VtIDwtIGFzLmRhdGEuZnJhbWUoZnJlYWQoZmlsZS5wYXRoKHBhdGgsImFzdl90YWJsZV9pa2VtLmNzdiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2submFtZXMgPSBGQUxTRSkpDQp0YXhhX3RhYl9pa2VtIDwtIGFzLmRhdGEuZnJhbWUoZnJlYWQoZmlsZS5wYXRoKHBhdGgsInRheGFfdGFibGVfaWtlbS5jc3YiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFKSkNCm1ldGFkYXRhX2lrZW0gPC0gYXMuZGF0YS5mcmFtZShmcmVhZChmaWxlLnBhdGgocGF0aCwibWV0YWRhdGFfaWtlbS5jc3YiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFKSkNCmBgYA0KDQoqKk5vcndheSoqDQoNCmBgYHtyfQ0KcGF0aCA9ICIuLi8uLi9kYXRhL2FuYWx5c2lzX3JlYWR5X2RhdGEvbm9yd2F5LyINCmFzdl90YWJfbm9yd2F5IDwtIGFzLmRhdGEuZnJhbWUoZnJlYWQoZmlsZS5wYXRoKHBhdGgsImFzdl90YWJsZV9ub3J3YXkuY3N2IiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVjay5uYW1lcyA9IEZBTFNFKSkNCnRheGFfdGFiX25vcndheSA8LSBhcy5kYXRhLmZyYW1lKGZyZWFkKGZpbGUucGF0aChwYXRoLCJ0YXhhX3RhYmxlX25vcndheS5jc3YiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRkFMU0UpKQ0KbWV0YWRhdGFfbm9yd2F5IDwtIGFzLmRhdGEuZnJhbWUoZnJlYWQoZmlsZS5wYXRoKHBhdGgsIm1ldGFkYXRhX25vcndheS5jc3YiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrLm5hbWVzID0gRkFMU0UpKQ0KYGBgDQoNCiMjIE1lcmdpbmcgZGF0YQ0KDQpNZXJnaW5nIHR3byBjb3VudHJpZXMgdG8gY3JlYXRlIHdob2xlIGRhdGFzZXQNCg0KYGBge3J9DQphc3ZfdGFiIDwtIG1lcmdlKGFzdl90YWJfaWtlbSxhc3ZfdGFiX25vcndheSxieT0iU2VxSUQiLGFsbD1UUlVFKQ0KdGF4YV90YWIgPC0gbWVyZ2luZ190YXhhX3RhYmxlcyh0YXhhX3RhYl9pa2VtLHRheGFfdGFiX25vcndheSkNCmBgYA0KDQpNZXJnaW5nIHR3byBjb3VudHJpZXMgYmFzZWQgb24gdGhlIGRpZmZlcmVudCBtYXRyaWNlcyAtIElsZXVtLCBDb2xvbi4NCg0KIyMjIFRlcm1pbmFsIGlsZXVtDQoNCmBgYHtyfQ0KaWxldW1fZGF0YSA8LSBtZXJnaW5nX2RhdGEoYXN2X3RhYl8xPWFzdl90YWJfaWtlbSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzdl90YWJfMj1hc3ZfdGFiX25vcndheSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFiXzE9dGF4YV90YWJfaWtlbSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFiXzI9dGF4YV90YWJfbm9yd2F5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGFfMT1tZXRhZGF0YV9pa2VtLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGFfMj1tZXRhZGF0YV9ub3J3YXksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PSJUSSIsUT0iUTIiKQ0KDQppbGV1bV9hc3ZfdGFiIDwtIGlsZXVtX2RhdGFbWzFdXQ0KaWxldW1fdGF4YV90YWIgPC0gaWxldW1fZGF0YVtbMl1dDQppbGV1bV9tZXRhZGF0YSA8LSBpbGV1bV9kYXRhW1szXV0NCmBgYA0KDQojIyMgQ29sb24NCg0KYGBge3J9DQpjb2xvbl9kYXRhIDwtIG1lcmdpbmdfZGF0YShhc3ZfdGFiXzE9YXN2X3RhYl9pa2VtLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgYXN2X3RhYl8yPWFzdl90YWJfbm9yd2F5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJfMT10YXhhX3RhYl9pa2VtLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJfMj10YXhhX3RhYl9ub3J3YXksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV8xPW1ldGFkYXRhX2lrZW0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV8yPW1ldGFkYXRhX25vcndheSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9ImNvbG9uIixRPSJRMiIpDQoNCmNvbG9uX2Fzdl90YWIgPC0gY29sb25fZGF0YVtbMV1dDQpjb2xvbl90YXhhX3RhYiA8LSBjb2xvbl9kYXRhW1syXV0NCmNvbG9uX21ldGFkYXRhIDwtIGNvbG9uX2RhdGFbWzNdXQ0KYGBgDQoNCiMgRGF0YSBBbmFseXNpcyAtIFRlcm1pbmFsIGlsZXVtDQoNCmBgYHtyfQ0Kc2VnbWVudD0idGVybWluYWxfaWxldW0iDQpgYGANCg0KIyMgRmlsdGVyaW5nDQoNClJ1bGVzOiAtIHByZXZhbGVuY2UgXD4gNSUgKHBlciBncm91cCkgLSBuZWFyWmVyb1ZhciB3aXRoIGRlZmF1bHQNCnNldHRpbmdzIC0gc2VxdWVuY2luZyBkZXB0aCBcPiA1MDAwIC0gdGF4b25vbWljIGFzc2lnbm1lbnQgYXQgbGVhc3QNCm9yZGVyDQoNCioqUmFyZWZhY3Rpb24gQ3VydmUqKg0KDQpgYGB7cn0NCnBhdGg9Ii4uL2ludGVybWVkaWF0ZV9maWxlcy9yYXJlY3VydmVzIg0Kc2VxX2RlcHRoX3RocmVzaG9sZCA8LSAxMDAwMA0KYGBgDQoNCmBgYHtyLCBldmFsID0gRkFMU0V9DQpwcyA8LSBjb25zdHJ1Y3RfcGh5bG9zZXEoaWxldW1fYXN2X3RhYixpbGV1bV90YXhhX3RhYixpbGV1bV9tZXRhZGF0YSkNCnJhcmVyZXMgPC0gZ2V0X3JhcmVjdXJ2ZShvYmo9cHMsIGNodW5rcz01MDApDQpzYXZlKHJhcmVyZXMsZmlsZSA9IGZpbGUucGF0aChwYXRoLCJyYXJlZmFjdGlvbl9pbGV1bS5SZGF0YSIpKQ0KYGBgDQoNCmBgYHtyfQ0KbG9hZChmaWxlLnBhdGgocGF0aCwicmFyZWZhY3Rpb25faWxldW0uUmRhdGEiKSkNCg0KcHJhcmUgPC0gZ2dyYXJlY3VydmUob2JqPXJhcmVyZXMsDQogICAgICAgICAgICAgICAgICAgICAgZmFjdG9yTmFtZXM9IkNvdW50cnkiLA0KICAgICAgICAgICAgICAgICAgICAgIGluZGV4TmFtZXM9YygiT2JzZXJ2ZSIpKSArIA0KICB0aGVtZV9idygpICsNCiAgdGhlbWUoYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpLCBwYW5lbC5ncmlkPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXI9TkEsZmlsbD0iZ3JleSIpLA0KICAgICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIpKSArIA0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBzZXFfZGVwdGhfdGhyZXNob2xkLCANCiAgICAgICAgICAgICBsaW5ldHlwZT0iZGFzaGVkIiwgDQogICAgICAgICAgICAgY29sb3IgPSAicmVkIikgKyANCiAgeGxpbSgwLCAyMDAwMCkNCg0KcHJhcmUNCmBgYA0KDQoqKkxpYnJhcnkgc2l6ZSoqDQoNCmBgYHtyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD00LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpyZWFkX2NvdW50cyhpbGV1bV9hc3ZfdGFiLCBsaW5lID0gYyg1MDAwLDEwMDAwKSkNCmBgYA0KDQojIyMgU2VxdWVuY2luZyBkZXB0aA0KDQpgYGB7cn0NCmRhdGFfZmlsdCA8LSBzZXFfZGVwdGhfZmlsdGVyaW5nKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VxX2RlcHRoX3RocmVzaG9sZCA9IDEwMDAwKQ0KDQpmaWx0X2lsZXVtX2Fzdl90YWIgPC0gZGF0YV9maWx0W1sxXV07IGFscGhhX2lsZXVtX2Fzdl90YWIgPC0gZmlsdF9pbGV1bV9hc3ZfdGFiDQpmaWx0X2lsZXVtX3RheGFfdGFiIDwtIGRhdGFfZmlsdFtbMl1dOyBhbHBoYV9pbGV1bV90YXhhX3RhYiA8LSBmaWx0X2lsZXVtX3RheGFfdGFiDQpmaWx0X2lsZXVtX21ldGFkYXRhIDwtIGRhdGFfZmlsdFtbM11dOyBhbHBoYV9pbGV1bV9tZXRhZGF0YSA8LSBmaWx0X2lsZXVtX21ldGFkYXRhDQoNCnNlcV9zdGVwIDwtIGRpbShmaWx0X2lsZXVtX2Fzdl90YWIpWzFdDQpgYGANCg0KKipMaWJyYXJ5IHNpemUqKg0KDQpgYGB7ciwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KcmVhZF9jb3VudHMoZmlsdF9pbGV1bV9hc3ZfdGFiLGxpbmUgPSBjKDUwMDAsMTAwMDApKQ0KYGBgDQoNCiMjIyBOZWFyWmVyb1Zhcg0KDQpgYGB7cn0NCmRhdGFfZmlsdCA8LSBuZWFyemVyb3Zhcl9maWx0ZXJpbmcoZmlsdF9pbGV1bV9hc3ZfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9tZXRhZGF0YSkNCg0KZmlsdF9pbGV1bV9hc3ZfdGFiIDwtIGRhdGFfZmlsdFtbMV1dDQpmaWx0X2lsZXVtX3RheGFfdGFiIDwtIGRhdGFfZmlsdFtbMl1dDQpuZWFyemVyb19zdGVwIDwtIGRpbShmaWx0X2lsZXVtX2Fzdl90YWIpWzFdDQpgYGANCg0KTGlicmFyeSBzaXplDQoNCmBgYHtyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD00LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpyZWFkX2NvdW50cyhmaWx0X2lsZXVtX2Fzdl90YWIsbGluZSA9IGMoNTAwMCwxMDAwMCkpDQpgYGANCg0KIyMjIEZpbmFsIENvdW50cw0KDQpgYGB7cn0NCmZpbmFsX2NvdW50c19maWx0ZXJpbmcoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICBzZXFfc3RlcCwgMCwgbmVhcnplcm9fc3RlcCkgJT4lIGBjb2xuYW1lczwtYCgiQ291bnQiKQ0KYGBgDQoNCiMjIEFscGhhIGRpdmVyc2l0eQ0KDQpgYGB7cn0NCnBhdGggPSAiLi4vcmVzdWx0cy9RMi9hbHBoYV9kaXZlcnNpdHkiDQpgYGANCg0KKipDYWxjdWxhdGlvbioqDQoNCmBgYHtyfQ0KIyBDb25zdHJ1Y3QgTVBTRSBvYmplY3QNCmFscGhhX2lsZXVtX21ldGFkYXRhJFNhbXBsZSA8LSBhbHBoYV9pbGV1bV9tZXRhZGF0YSRTYW1wbGVJRA0KaWxldW1fbXBzZSA8LSBhcy5NUFNFKGNvbnN0cnVjdF9waHlsb3NlcShhbHBoYV9pbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYV9pbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxwaGFfaWxldW1fbWV0YWRhdGEpKQ0KDQppbGV1bV9tcHNlICU8PiUgbXBfcnJhcmVmeShyYXJlc2l6ZSA9IDEwMDAwLHNlZWQgPSAxMjMpDQoNCiMgQ2FsY3VsYXRlIGFscGhhIGRpdmVyc2l0eSAtIHJhcmVmaWVkIGNvdW50cw0KaWxldW1fbXBzZSAlPD4lIG1wX2NhbF9hbHBoYSguYWJ1bmRhbmNlPVJhcmVBYnVuZGFuY2UsIGZvcmNlPVRSVUUpDQpgYGANCg0KYGBge3J9DQoNCmFscGhhX2Rpdl9wbG90cyA8LSBsaXN0KCkNCg0KIyBwcmVwYXJpbmcgZGF0YSBmcmFtZQ0KYWxwaGFfZGF0YSA8LSBkYXRhLmZyYW1lKFNhbXBsZUlEPWlsZXVtX21wc2UkU2FtcGxlLngsDQogICAgICAgICAgICAgICAgICAgICAgICAgT2JzZXJ2ZT1pbGV1bV9tcHNlJE9ic2VydmUsDQogICAgICAgICAgICAgICAgICAgICAgICAgU2hhbm5vbj1pbGV1bV9tcHNlJFNoYW5ub24sDQogICAgICAgICAgICAgICAgICAgICAgICAgU2ltcHNvbj1pbGV1bV9tcHNlJFNpbXBzb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgUGllbG91PWlsZXVtX21wc2UkUGllbG91LA0KICAgICAgICAgICAgICAgICAgICAgICAgIEdyb3VwPWlsZXVtX21wc2UkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgQ291bnRyeT1pbGV1bV9tcHNlJENvdW50cnksDQogICAgICAgICAgICAgICAgICAgICAgICAgUGF0aWVudD1pbGV1bV9tcHNlJFBhdGllbnQpDQoNCndyaXRlLmNzdihhbHBoYV9kYXRhLGZpbGUucGF0aChwYXRoLHBhc3RlMCgiYWxwaGFfaW5kaWNlc18iLHNlZ21lbnQsIi5jc3YiKSksDQogICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KKipQbG90cyoqDQoNCiMjIyBDb3VudHJ5IHBsb3QNCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpwX2JveHBsb3RfYWxwaGEgPC0gYWxwaGFfZGl2ZXJzaXR5X2NvdW50cmllcyhhbHBoYV9kYXRhKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCmFscGhhX2Rpdl9wbG90c1tbcGFzdGUoc2VnbWVudCwiQ291bnRyeSIpXV0gPC0gcF9ib3hwbG90X2FscGhhDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpwX2JveHBsb3RfYWxwaGENCmBgYA0KDQpgYGB7cixyZXN1bHRzPSdoaWRlJ30NCnBkZigiLi4vZmlndXJlcy9RMi9hbHBoYV9kaXZlcnNpdHlfdGVybWluYWxfaWxldW0ucGRmIiwNCiAgICBoZWlnaHQgPTQsd2lkdGggPSA3KQ0KcF9ib3hwbG90X2FscGhhDQpkZXYub2ZmKCkNCmBgYA0KDQojIyMgQ3VzdG9tIHBsb3QNCg0KYGBge3IsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTQsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCmFscGhhX2RhdGEgPC0gYWxwaGFfZGF0YSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoLWMoIlNpbXBzb24iLCJQaWVsb3UiKSkgJT4lDQogIG11dGF0ZShSaWNobmVzcz1PYnNlcnZlKQ0KDQpwX0EgPC0gYWxwaGFfZGl2ZXJzaXR5X2N1c3RvbV8yKGFscGhhX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gMC4zKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCmFscGhhX2Rpdl9wbG90c1tbcGFzdGUoc2VnbWVudCwiQ3VzdG9tIildXSA8LSBwX0ENCg0KcF9BDQpgYGANCg0KIyMjIExpbmVhciBNb2RlbA0KDQpgYGB7cn0NCnBhdGggPSAiLi4vcmVzdWx0cy9RMi9hbHBoYV9kaXZlcnNpdHkiDQphbHBoYV9kYXRhIDwtIHJlYWQuY3N2KGZpbGUucGF0aChwYXRoLHBhc3RlMCgiYWxwaGFfaW5kaWNlc18iLHNlZ21lbnQsIi5jc3YiKSkpDQpgYGANCg0KKipSaWNobmVzcyoqDQoNCmBgYHtyfQ0KcmVzdWx0c19tb2RlbCA8LSBwYWlyd2lzZS5sbShmb3JtdWxhID0gIk9ic2VydmUgfiBHcm91cCAqIENvdW50cnkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWN0b3JzPWFscGhhX2RhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9YWxwaGFfZGF0YSkNCg0KIyBjaGVjayBpbnRlcmFjdGlvbg0KaWYgKCFpcy5kYXRhLmZyYW1lKHJlc3VsdHNfbW9kZWwpKXsNCiAgcmVzdWx0c19tb2RlbF9vYnNlcnZlIDwtIHJlc3VsdHNfbW9kZWxbWzFdXQ0KICByZXN1bHRzX21vZGVsX29ic2VydmVfZW1lYW5zIDwtIHJlc3VsdHNfbW9kZWxbWzJdXQ0KfSBlbHNlIHsNCiAgcmVzdWx0c19tb2RlbF9vYnNlcnZlIDwtIHJlc3VsdHNfbW9kZWwNCiAgcmVzdWx0c19tb2RlbF9vYnNlcnZlX2VtZWFucyA8LSBOQQ0KfQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnBjX29ic2VydmVkIDwtIGxpc3QoKTsgDQpwY19vYnNlcnZlZFtbc2VnbWVudF1dIDwtIHJlc3VsdHNfbW9kZWxfb2JzZXJ2ZQ0KYGBgDQoNCmBgYHtyfQ0KIyBzZWUgdGhlIHJlc3VsdHMNCmtuaXRyOjprYWJsZShyZXN1bHRzX21vZGVsX29ic2VydmUsZGlnaXRzID0gMywNCmNhcHRpb24gPSAiUmF3IHJlc3VsdHMgb2YgbGluZWFyIG1vZGVsIG9mIHJpY2huZXNzIGVzdGltYXRpb24uIikNCg0Ka25pdHI6OmthYmxlKHJlc3VsdHNfbW9kZWxfb2JzZXJ2ZV9lbWVhbnMsZGlnaXRzID0gMywNCmNhcHRpb24gPSAiUmF3IHJlc3VsdHMgb2YgaW5kZXBlbmRlbnQgY291bnRyeSBhbmFseXNpcyIpDQpgYGANCg0KKipTaGFubm9uKioNCg0KYGBge3J9DQpyZXN1bHRzX21vZGVsIDwtIHBhaXJ3aXNlLmxtKGZvcm11bGEgPSAiU2hhbm5vbiB+IEdyb3VwICogQ291bnRyeSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY3RvcnM9YWxwaGFfZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1hbHBoYV9kYXRhKQ0KDQojIGNoZWNrIGludGVyYWN0aW9uDQppZiAoIWlzLmRhdGEuZnJhbWUocmVzdWx0c19tb2RlbCkpew0KICByZXN1bHRzX21vZGVsX3NoYW5ub24gPC0gcmVzdWx0c19tb2RlbFtbMV1dDQogIHJlc3VsdHNfbW9kZWxfc2hhbm5vbl9lbWVhbnMgPC0gcmVzdWx0c19tb2RlbFtbMl1dDQp9IGVsc2Ugew0KICByZXN1bHRzX21vZGVsX3NoYW5ub24gPC0gcmVzdWx0c19tb2RlbA0KICByZXN1bHRzX21vZGVsX3NoYW5ub25fZW1lYW5zIDwtIE5BDQp9DQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KcGNfc2hhbm5vbiA8LSBsaXN0KCk7IA0KcGNfc2hhbm5vbltbc2VnbWVudF1dIDwtIGFzLmRhdGEuZnJhbWUocmVzdWx0c19tb2RlbF9zaGFubm9uKQ0KDQpgYGANCg0KYGBge3J9DQojIHNlZSB0aGUgcmVzdWx0cw0Ka25pdHI6OmthYmxlKHJlc3VsdHNfbW9kZWxfc2hhbm5vbixkaWdpdHMgPSAzLA0KY2FwdGlvbiA9ICJSYXcgcmVzdWx0cyBvZiBsaW5lYXIgbW9kZWwgb2YgU2hhbm5vbiBlc3RpbWF0aW9uLiIpDQoNCmtuaXRyOjprYWJsZShyZXN1bHRzX21vZGVsX3NoYW5ub25fZW1lYW5zLGRpZ2l0cyA9IDMsDQpjYXB0aW9uID0gIlJhdyByZXN1bHRzIG9mIGluZGVwZW5kZW50IGNvdW50cnkgYW5hbHlzaXMiKQ0KYGBgDQoNCioqU2ltcHNvbioqDQoNCmBgYHtyfQ0KcmVzdWx0c19tb2RlbCA8LSBwYWlyd2lzZS5sbShmb3JtdWxhID0gIlNpbXBzb24gfiBHcm91cCAqIENvdW50cnkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY3RvcnM9YWxwaGFfZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWFscGhhX2RhdGEpDQoNCiMgY2hlY2sgaW50ZXJhY3Rpb24NCmlmICghaXMuZGF0YS5mcmFtZShyZXN1bHRzX21vZGVsKSl7DQogIHJlc3VsdHNfbW9kZWxfc2ltcHNvbiA8LSByZXN1bHRzX21vZGVsW1sxXV0NCiAgcmVzdWx0c19tb2RlbF9zaW1wc29uX2VtZWFucyA8LSByZXN1bHRzX21vZGVsW1syXV0NCn0gZWxzZSB7DQogIHJlc3VsdHNfbW9kZWxfc2ltcHNvbiA8LSByZXN1bHRzX21vZGVsDQogIHJlc3VsdHNfbW9kZWxfc2ltcHNvbl9lbWVhbnMgPC0gTkENCn0NCg0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnBjX3NpbXBzb24gPC0gbGlzdCgpOyANCnBjX3NpbXBzb25bW3NlZ21lbnRdXSA8LSBhcy5kYXRhLmZyYW1lKHJlc3VsdHNfbW9kZWxfc2ltcHNvbikNCmBgYA0KDQpgYGB7cn0NCiMgc2VlIHRoZSByZXN1bHRzDQprbml0cjo6a2FibGUocmVzdWx0c19tb2RlbF9zaW1wc29uLGRpZ2l0cyA9IDMsDQpjYXB0aW9uID0gIlJhdyByZXN1bHRzIG9mIGxpbmVhciBtb2RlbCBvZiBTaW1wc29uIGVzdGltYXRpb24uIikNCg0Ka25pdHI6OmthYmxlKHJlc3VsdHNfbW9kZWxfc2ltcHNvbl9lbWVhbnMsZGlnaXRzID0gMywNCmNhcHRpb24gPSAiUmF3IHJlc3VsdHMgb2YgaW5kZXBlbmRlbnQgY291bnRyeSBhbmFseXNpcyIpDQpgYGANCg0KKipQaWVsb3UqKg0KDQpgYGB7cn0NCnJlc3VsdHNfbW9kZWwgPC0gcGFpcndpc2UubG0oZm9ybXVsYSA9ICJQaWVsb3UgfiBHcm91cCAqIENvdW50cnkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY3RvcnM9YWxwaGFfZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWFscGhhX2RhdGEpDQoNCiMgY2hlY2sgaW50ZXJhY3Rpb24NCg0KaWYgKCFpcy5kYXRhLmZyYW1lKHJlc3VsdHNfbW9kZWwpKXsNCiAgcmVzdWx0c19tb2RlbF9waWVsb3UgPC0gcmVzdWx0c19tb2RlbFtbMV1dDQogIHJlc3VsdHNfbW9kZWxfcGllbG91X2VtZWFucyA8LSByZXN1bHRzX21vZGVsW1syXV0NCn0gZWxzZSB7DQogIHJlc3VsdHNfbW9kZWxfcGllbG91IDwtIHJlc3VsdHNfbW9kZWwNCiAgcmVzdWx0c19tb2RlbF9waWVsb3VfZW1lYW5zIDwtIE5BDQp9DQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KcGNfcGllbG91IDwtIGxpc3QoKTsgDQpwY19waWVsb3VbW3NlZ21lbnRdXSA8LSBhcy5kYXRhLmZyYW1lKHJlc3VsdHNfbW9kZWxfcGllbG91KQ0KYGBgDQoNCmBgYHtyfQ0KIyBzZWUgdGhlIHJlc3VsdHMNCmtuaXRyOjprYWJsZShyZXN1bHRzX21vZGVsX3BpZWxvdSxkaWdpdHMgPSAzLA0KY2FwdGlvbiA9ICJSYXcgcmVzdWx0cyBvZiBsaW5lYXIgbW9kZWwgb2YgUGllbG91IGVzdGltYXRpb24uIikNCg0Ka25pdHI6OmthYmxlKHJlc3VsdHNfbW9kZWxfcGllbG91X2VtZWFucyxkaWdpdHMgPSAzLA0KY2FwdGlvbiA9ICJSYXcgcmVzdWx0cyBvZiBpbmRlcGVuZGVudCBjb3VudHJ5IGFuYWx5c2lzIikNCmBgYA0KIyMjIFNhdmluZyByZXN1bHRzDQoNCmBgYHtyfQ0KYWxwaGFfbGlzdCA8LSBsaXN0KA0KICBSaWNobmVzcz1wY19vYnNlcnZlZFtbc2VnbWVudF1dICU+JSByb3duYW1lc190b19jb2x1bW4oIkNvbXBhcmlzb24iKSwNCiAgU2hhbm5vbj1wY19zaGFubm9uW1tzZWdtZW50XV0gJT4lIHJvd25hbWVzX3RvX2NvbHVtbigiQ29tcGFyaXNvbiIpLA0KICBTaW1wc29uPXBjX3NpbXBzb25bW3NlZ21lbnRdXSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJDb21wYXJpc29uIiksDQogIFBpZWxvdT1wY19waWVsb3VbW3NlZ21lbnRdXSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJDb21wYXJpc29uIikpDQogICAgICAgICAgICAgICAgICAgDQp3cml0ZS54bHN4KGFscGhhX2xpc3QsIA0KICAgICAgICAgICBmaWxlID0gZmlsZS5wYXRoKHBhdGgscGFzdGUwKCJhbHBoYV9kaXZlcnNpdHlfcmVzdWx0c18iLHNlZ21lbnQsIi54bHN4IikpKQ0KYGBgDQoNCiMjIEJldGEgZGl2ZXJzaXR5DQoNCkNhbGN1bGF0aW5nIEFpdGNoaXNvbiBkaXN0YW5jZSAoZXVjbGlkZWFuIGRpc3RhbmNlIG9uIGNsci10cmFuc2Zvcm1lZA0KZGF0YSksIGJvdGggYXQgQVNWIGFuZCBnZW51cyBsZXZlbC4NCg0KIyMjIE1haW4gYW5hbHlzaXMgLSBHZW51cywgQWl0Y2hpc29uDQoNCioqR2VudXMgbGV2ZWwsIEFpdGNoaXNvbiBkaXN0YW5jZSoqDQoNCmBgYHtyfQ0KbGV2ZWw9ImdlbnVzIg0KYGBgDQoNCmBgYHtyfQ0KcGF0aCA9ICIuLi9yZXN1bHRzL1EyL2JldGFfZGl2ZXJzaXR5Ig0KYGBgDQoNCmBgYHtyfQ0KcGFpcndpc2VfYWl0Y2hpc29uX3JhdyA8LSBsaXN0KCkNCnBjYV9wbG90c19saXN0IDwtIGxpc3QoKQ0KYGBgDQoNCkFnZ3JlZ2F0aW9uLCBmaWx0ZXJpbmcNCg0KYGBge3J9DQojIEFnZ3JlZ2F0aW9uDQpnZW51c19kYXRhIDwtIGFnZ3JlZ2F0ZV90YXhhKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhvbm9taWNfbGV2ZWw9bGV2ZWwsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzPVRSVUUpDQojIEZpbHRyYXRpb24NCmZpbHRfZGF0YSA8LSBmaWx0ZXJpbmdfc3RlcHMoZ2VudXNfZGF0YVtbMV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW51c19kYXRhW1syXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXFfZGVwdGhfdGhyZXNob2xkPTEwMDAwKQ0KDQpmaWx0X2lsZXVtX2dlbnVzX3RhYiA8LSBmaWx0X2RhdGFbWzFdXQ0KZmlsdF9pbGV1bV9nZW51c190YXhhIDwtIGZpbHRfZGF0YVtbMl1dDQpmaWx0X2lsZXVtX21ldGFkYXRhIDwtIGZpbHRfZGF0YVtbM11dDQpgYGANCg0KIyMjIyMgUEVSTUFOT1ZBDQoNCmBgYHtyfQ0KcGFpcndpc2VfZGYgPC0gZmlsdF9pbGV1bV9nZW51c190YWIgJT4lIGNvbHVtbl90b19yb3duYW1lcygiU2VxSUQiKSAlPiUgdCgpDQoNCiMgbWFpbiBlZmZlY3QNCnBwX21haW4gPC0gcGFpcndpc2UuYWRvbmlzKHBhaXJ3aXNlX2RmLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9tZXRhZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgc2ltLm1ldGhvZCA9ICJyb2J1c3QuYWl0Y2hpc29uIiwgcC5hZGp1c3QubT0iQkgiKQ0KDQojIGludGVyYWN0aW9uDQpwcF9pbnQgPC0gcGFpcndpc2UuYWRvbmlzKHBhaXJ3aXNlX2RmLGZpbHRfaWxldW1fbWV0YWRhdGEkR3JvdXAsY292YXJpYXRlID0gZmlsdF9pbGV1bV9tZXRhZGF0YSRDb3VudHJ5LCBpbnRlcmFjdGlvbiA9IFRSVUUsIHNpbS5tZXRob2QgPSAicm9idXN0LmFpdGNoaXNvbiIsIHAuYWRqdXN0Lm09IkJIIikNCg0KIyB0aWR5IHRoZSByZXN1bHRzDQpwcF9mYWN0b3IgPC0gcHBfbWFpbltbMV1dDQpwcF9jb3YgPC0gcHBfbWFpbltbMl1dDQpwcF9mYWMuY292IDwtIHBwX2ludFtbM11dDQoNCmNvbHMgPC0gYygicGFpcnMiLCJEZiIsIlN1bXNPZlNxcyIsICJGLk1vZGVsIiwiUjIiLCJwLnZhbHVlIiwgInAuYWRqdXN0ZWQiLCAic2lnIikNCmNvbG5hbWVzKHBwX2ZhY3RvcikgPC0gY29sczsgY29sbmFtZXMocHBfY292KSA8LSBjb2xzOyBjb2xuYW1lcyhwcF9mYWMuY292KSA8LSBjb2xzOyANCg0KIyBzYXZlIHJhdyByZXN1bHRzDQpwYWlyd2lzZV9haXRjaGlzb25fcmF3W1twYXN0ZShsZXZlbCwgc2VnbWVudCldXSA8LSByYmluZChwcF9mYWN0b3IscHBfY292LHBwX2ZhYy5jb3YpDQpgYGANCg0KYGBge3J9DQojIHNlZSB0aGUgcmVzdWx0cw0Ka25pdHI6OmthYmxlKHBwX2ZhY3RvcixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBHUk9VUCBzZXBhcmF0aW9uIikNCmtuaXRyOjprYWJsZShwcF9jb3YsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgQ09VTlRSWSBzZXBhcmF0aW9uIikNCmtuaXRyOjprYWJsZShwcF9mYWMuY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIElOVEVSQUNUSU9OIEdST1VQOkNvdW50cnkiKQ0KYGBgDQoNCkludGVyYWN0aW9uIGNoZWNrDQoNCmBgYHtyfQ0KaW50ZXJhY3Rpb25fc2lnIDwtIHBwX2ZhYy5jb3YkcGFpcnNbcHBfZmFjLmNvdiRwLmFkanVzdGVkIDwgMC4wNV0NCg0KaWYgKGxlbmd0aChpbnRlcmFjdGlvbl9zaWcpPjApew0KICBmb3IgKGkgaW4gMTpsZW5ndGgoaW50ZXJhY3Rpb25fc2lnKSl7DQogIGdyb3VwMSA8LSB1bmxpc3Qoc3Ryc3BsaXQoaW50ZXJhY3Rpb25fc2lnW2ldLHNwbGl0ID0gIiB2cyAiKSlbMV0NCiAgZ3JvdXAyIDwtIHVubGlzdChzdHJzcGxpdChpbnRlcmFjdGlvbl9zaWdbaV0sc3BsaXQgPSAiIHZzICIpKVsyXQ0KICBncm91cDIgPC0gdW5saXN0KHN0cnNwbGl0KGdyb3VwMixzcGxpdCA9ICIgOiAiKSlbMV0NCiAgDQogIHJlc3VsdF9saXN0IDwtIGFkb25pc19wb3N0YW5hbHlzaXMoeD1wYWlyd2lzZV9kZiwNCiAgICAgICAgICAgICAgICAgICAgICBmYWN0b3JzID0gZmlsdF9pbGV1bV9tZXRhZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGUgPSBmaWx0X2lsZXVtX21ldGFkYXRhJENvdW50cnksIA0KICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMSA9IGdyb3VwMSwNCiAgICAgICAgICAgICAgICAgICAgICBncm91cDIgPSBncm91cDIpDQogIHByaW50KHJlc3VsdF9saXN0KQ0KfQ0KfQ0KDQoNCmBgYA0KDQojIyMjIyBQbG90cw0KDQoqKkN1c3RvbSoqDQoNCmBgYHtyfQ0KcCA8LSBwY2FfcGxvdF9jdXN0b20oZmlsdF9pbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX2dlbnVzX3RheGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19ib3hwbG90cyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZSA9ICJHcm91cCIsIHNpemU9Mywgc2hvd19sZWdlbmQ9RkFMU0UpDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KcGNhX3Bsb3RzX2xpc3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsImN1c3RvbSIpXV0gPC0gcA0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcA0KYGBgDQpgYGB7cixyZXN1bHRzPSdoaWRlJ30NCnBkZigiLi4vZmlndXJlcy9RMi9iZXRhX2RpdmVyc2l0eV90ZXJtaW5hbF9pbGV1bS5wZGYiLA0KICAgIGhlaWdodCA9NSx3aWR0aCA9IDUpDQpwDQpkZXYub2ZmKCkNCmBgYA0KDQojIyMjIFNhdmluZyByZXN1bHRzDQoNCmBgYHtyfQ0Kd3JpdGUueGxzeChwYWlyd2lzZV9haXRjaGlzb25fcmF3W1twYXN0ZShsZXZlbCwgc2VnbWVudCldXSwgDQogICAgICAgICAgIGZpbGUgPSBmaWxlLnBhdGgocGF0aCwNCiAgICAgICAgICAgcGFzdGUwKCJiZXRhX2RpdmVyc2l0eV9yZXN1bHRzXyIsIHNlZ21lbnQsIi54bHN4IikpKQ0KYGBgDQoNCiMjIyBTdXBwbGVtZW50YXJ5IGFuYWx5c2lzDQoNCmBgYHtyfQ0Kc3VwcGxlbWVudHNfYmV0YSA8LSBsaXN0KCkNCmBgYA0KDQojIyMjIEdlbnVzIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9ImdlbnVzIg0KYGBgDQoNCiMjIyMjIEJyYXktQ3VydGlzDQoNCioqUEVSTUFOT1ZBKioNCg0KYGBge3J9DQpwYWlyd2lzZV9kZiA8LSBmaWx0X2lsZXVtX2dlbnVzX3RhYiAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJTZXFJRCIpICU+JSB0KCkNCg0KIyBtYWluIGVmZmVjdA0KcHBfbWFpbiA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsZmlsdF9pbGV1bV9tZXRhZGF0YSRHcm91cCxjb3ZhcmlhdGUgPSBmaWx0X2lsZXVtX21ldGFkYXRhJENvdW50cnksIHNpbS5tZXRob2QgPSAiYnJheSIsIHAuYWRqdXN0Lm09IkJIIikNCg0KIyBpbnRlcmFjdGlvbg0KcHBfaW50IDwtIHBhaXJ3aXNlLmFkb25pcyhwYWlyd2lzZV9kZixmaWx0X2lsZXVtX21ldGFkYXRhJEdyb3VwLGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgaW50ZXJhY3Rpb24gPSBUUlVFLCBzaW0ubWV0aG9kID0gImJyYXkiLCBwLmFkanVzdC5tPSJCSCIpDQoNCiMgdGlkeSB0aGUgcmVzdWx0cw0KcHBfZmFjdG9yIDwtIHBwX21haW5bWzFdXQ0KcHBfY292IDwtIHBwX21haW5bWzJdXQ0KcHBfZmFjLmNvdiA8LSBwcF9pbnRbWzNdXQ0KDQpjb2xzIDwtIGMoInBhaXJzIiwiRGYiLCJTdW1zT2ZTcXMiLCAiRi5Nb2RlbCIsIlIyIiwicC52YWx1ZSIsICJwLmFkanVzdGVkIiwgInNpZyIpDQpjb2xuYW1lcyhwcF9mYWN0b3IpIDwtIGNvbHM7IGNvbG5hbWVzKHBwX2NvdikgPC0gY29sczsgY29sbmFtZXMocHBfZmFjLmNvdikgPC0gY29sczsgDQoNCiMgc2F2ZSByYXcgcmVzdWx0cw0Kc3VwcGxlbWVudHNfYmV0YVtbcGFzdGUoImJyYXkiLGxldmVsLHNlZ21lbnQpXV0gPC0gcmJpbmQocHBfZmFjdG9yLHBwX2NvdixwcF9mYWMuY292KQ0KYGBgDQoNCmBgYHtyfQ0KIyBzZWUgdGhlIHJlc3VsdHMNCmtuaXRyOjprYWJsZShwcF9mYWN0b3IsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgR1JPVVAgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIENPVU5UUlkgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfZmFjLmNvdixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBJTlRFUkFDVElPTiBHUk9VUDpDb3VudHJ5IikNCmBgYA0KDQpJbnRlcmFjdGlvbiBjaGVjaw0KDQpgYGB7cn0NCmludGVyYWN0aW9uX3NpZyA8LSBwcF9mYWMuY292JHBhaXJzW3BwX2ZhYy5jb3YkcC5hZGp1c3RlZCA8IDAuMDVdDQoNCmZvciAoaSBpbiAxOmxlbmd0aChpbnRlcmFjdGlvbl9zaWcpKXsNCiAgZ3JvdXAxIDwtIHVubGlzdChzdHJzcGxpdChpbnRlcmFjdGlvbl9zaWdbaV0sc3BsaXQgPSAiIHZzICIpKVsxXQ0KICBncm91cDIgPC0gdW5saXN0KHN0cnNwbGl0KGludGVyYWN0aW9uX3NpZ1tpXSxzcGxpdCA9ICIgdnMgIikpWzJdDQogIGdyb3VwMiA8LSB1bmxpc3Qoc3Ryc3BsaXQoZ3JvdXAyLHNwbGl0ID0gIiA6ICIpKVsxXQ0KICANCiAgcmVzdWx0X2xpc3QgPC0gYWRvbmlzX3Bvc3RhbmFseXNpcyh4PXBhaXJ3aXNlX2RmLA0KICAgICAgICAgICAgICAgICAgICAgIGZhY3RvcnMgPSBmaWx0X2lsZXVtX21ldGFkYXRhJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAxID0gZ3JvdXAxLA0KICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMiA9IGdyb3VwMiwNCiAgICAgICAgICAgICAgICAgICAgICBzaW0ubWV0aG9kID0gJ2JyYXknKQ0KICBwcmludChyZXN1bHRfbGlzdCkNCn0NCg0KYGBgDQoNCioqUGxvdHMqKg0KDQpgYGB7cn0NCnAgPC0gcGNhX3Bsb3RfY3VzdG9tKGZpbHRfaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9nZW51c190YXhhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPSAiYnJheSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2JveHBsb3RzID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlID0gIkdyb3VwIiwgc2l6ZT0zLCBzaG93X2xlZ2VuZD1GQUxTRSkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiUENvQSBicmF5IixsZXZlbCxzZWdtZW50KV1dIDwtIHANCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnANCmBgYA0KDQojIyMjIyBKYWNjYXJkDQoNCioqUEVSTUFOT1ZBKioNCg0KYGBge3J9DQpwYWlyd2lzZV9kZiA8LSBmaWx0X2lsZXVtX2dlbnVzX3RhYiAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJTZXFJRCIpICU+JSB0KCkNCg0KIyBtYWluIGVmZmVjdA0KcHBfbWFpbiA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsZmlsdF9pbGV1bV9tZXRhZGF0YSRHcm91cCxjb3ZhcmlhdGUgPSBmaWx0X2lsZXVtX21ldGFkYXRhJENvdW50cnksIHNpbS5tZXRob2QgPSAiamFjY2FyZCIsIHAuYWRqdXN0Lm09IkJIIikNCg0KIyBpbnRlcmFjdGlvbg0KcHBfaW50IDwtIHBhaXJ3aXNlLmFkb25pcyhwYWlyd2lzZV9kZixmaWx0X2lsZXVtX21ldGFkYXRhJEdyb3VwLGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgaW50ZXJhY3Rpb24gPSBUUlVFLCBzaW0ubWV0aG9kID0gImphY2NhcmQiLCBwLmFkanVzdC5tPSJCSCIpDQoNCiMgdGlkeSB0aGUgcmVzdWx0cw0KcHBfZmFjdG9yIDwtIHBwX21haW5bWzFdXQ0KcHBfY292IDwtIHBwX21haW5bWzJdXQ0KcHBfZmFjLmNvdiA8LSBwcF9pbnRbWzNdXQ0KDQpjb2xzIDwtIGMoInBhaXJzIiwiRGYiLCJTdW1zT2ZTcXMiLCAiRi5Nb2RlbCIsIlIyIiwicC52YWx1ZSIsICJwLmFkanVzdGVkIiwgInNpZyIpDQpjb2xuYW1lcyhwcF9mYWN0b3IpIDwtIGNvbHM7IGNvbG5hbWVzKHBwX2NvdikgPC0gY29sczsgY29sbmFtZXMocHBfZmFjLmNvdikgPC0gY29sczsgDQoNCiMgc2F2ZSByYXcgcmVzdWx0cw0Kc3VwcGxlbWVudHNfYmV0YVtbcGFzdGUoImphY2NhcmQiLGxldmVsLHNlZ21lbnQpXV0gPC0gcmJpbmQocHBfZmFjdG9yLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBwX2NvdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcF9mYWMuY292KQ0KYGBgDQoNCmBgYHtyfQ0KIyBzZWUgdGhlIHJlc3VsdHMNCmtuaXRyOjprYWJsZShwcF9mYWN0b3IsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgR1JPVVAgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIENPVU5UUlkgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfZmFjLmNvdixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBJTlRFUkFDVElPTiBHUk9VUDpDb3VudHJ5IikNCmBgYA0KDQpJbnRlcmFjdGlvbiBjaGVjaw0KDQpgYGB7cn0NCmludGVyYWN0aW9uX3NpZyA8LSBwcF9mYWMuY292JHBhaXJzW3BwX2ZhYy5jb3YkcC5hZGp1c3RlZCA8IDAuMDVdDQoNCmZvciAoaSBpbiAxOmxlbmd0aChpbnRlcmFjdGlvbl9zaWcpKXsNCiAgZ3JvdXAxIDwtIHVubGlzdChzdHJzcGxpdChpbnRlcmFjdGlvbl9zaWdbaV0sc3BsaXQgPSAiIHZzICIpKVsxXQ0KICBncm91cDIgPC0gdW5saXN0KHN0cnNwbGl0KGludGVyYWN0aW9uX3NpZ1tpXSxzcGxpdCA9ICIgdnMgIikpWzJdDQogIGdyb3VwMiA8LSB1bmxpc3Qoc3Ryc3BsaXQoZ3JvdXAyLHNwbGl0ID0gIiA6ICIpKVsxXQ0KICANCiAgcmVzdWx0X2xpc3QgPC0gYWRvbmlzX3Bvc3RhbmFseXNpcyh4PXBhaXJ3aXNlX2RmLA0KICAgICAgICAgICAgICAgICAgICAgIGZhY3RvcnMgPSBmaWx0X2lsZXVtX21ldGFkYXRhJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAxID0gZ3JvdXAxLA0KICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMiA9IGdyb3VwMiwNCiAgICAgICAgICAgICAgICAgICAgICBzaW0ubWV0aG9kID0gJ2phY2NhcmQnKQ0KICBwcmludChyZXN1bHRfbGlzdCkNCn0NCg0KYGBgDQoNCioqUGxvdHMqKg0KDQoqQ3VzdG9tKg0KDQpgYGB7cn0NCnAgPC0gcGNhX3Bsb3RfY3VzdG9tKGZpbHRfaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9nZW51c190YXhhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPSAiamFjY2FyZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2JveHBsb3RzID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlID0gIkdyb3VwIiwgc2l6ZT0zLCBzaG93X2xlZ2VuZD1GQUxTRSkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiUENvQSBqYWNjYXJkIixsZXZlbCxzZWdtZW50KV1dIDwtIHANCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnANCmBgYA0KDQojIyMjIEFTViBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJBU1YiDQpgYGANCg0KIyMjIyMgQWl0Y2hpc29uIA0KDQoqUEVSTUFOT1ZBKg0KDQpgYGB7cn0NCiMgcHJlcGFyaW5nIGRhdGEgZnJhbWUNCnBhaXJ3aXNlX2RmIDwtIGZpbHRfaWxldW1fYXN2X3RhYiAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJTZXFJRCIpICU+JSB0KCkNCg0KIyBtYWluIGVmZmVjdA0KcHBfbWFpbiA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsZmlsdF9pbGV1bV9tZXRhZGF0YSRHcm91cCxjb3ZhcmlhdGUgPSBmaWx0X2lsZXVtX21ldGFkYXRhJENvdW50cnksIHNpbS5tZXRob2QgPSAicm9idXN0LmFpdGNoaXNvbiIsIHAuYWRqdXN0Lm09IkJIIikNCg0KIyBpbnRlcmFjdGlvbg0KcHBfaW50IDwtIHBhaXJ3aXNlLmFkb25pcyhwYWlyd2lzZV9kZixmaWx0X2lsZXVtX21ldGFkYXRhJEdyb3VwLGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgaW50ZXJhY3Rpb24gPSBUUlVFLCBzaW0ubWV0aG9kID0gInJvYnVzdC5haXRjaGlzb24iLCBwLmFkanVzdC5tPSJCSCIpDQoNCnBwX2ZhY3RvciA8LSBwcF9tYWluW1sxXV0NCnBwX2NvdiA8LSBwcF9tYWluW1syXV0NCnBwX2ZhYy5jb3YgPC0gcHBfaW50W1szXV0NCg0KY29scyA8LSBjKCJwYWlycyIsIkRmIiwiU3Vtc09mU3FzIiwgIkYuTW9kZWwiLCJSMiIsInAudmFsdWUiLCAicC5hZGp1c3RlZCIsICJzaWciKQ0KY29sbmFtZXMocHBfZmFjdG9yKSA8LSBjb2xzOyBjb2xuYW1lcyhwcF9jb3YpIDwtIGNvbHM7IGNvbG5hbWVzKHBwX2ZhYy5jb3YpIDwtIGNvbHM7IA0KDQojIHNhdmUgcmF3IHJlc3VsdHMNCnN1cHBsZW1lbnRzX2JldGFbW3Bhc3RlKCJhaXRjaGlzb24iLGxldmVsLHNlZ21lbnQpXV0gPC0gcmJpbmQocHBfZmFjdG9yLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBwX2NvdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcF9mYWMuY292KQ0KYGBgDQoNCmBgYHtyfQ0KIyBzZWUgdGhlIHJlc3VsdHMNCmtuaXRyOjprYWJsZShwcF9mYWN0b3IsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgR1JPVVAgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIENPVU5UUlkgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfZmFjLmNvdixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBJTlRFUkFDVElPTiBHUk9VUDpDb3VudHJ5IikNCmBgYA0KDQpJbnRlcmFjdGlvbiBjaGVjaw0KDQpgYGB7cn0NCmludGVyYWN0aW9uX3NpZyA8LSBwcF9mYWMuY292JHBhaXJzW3BwX2ZhYy5jb3YkcC5hZGp1c3RlZCA8IDAuMDVdDQoNCmlmIChsZW5ndGgoaW50ZXJhY3Rpb25fc2lnKT4wKXsNCmZvciAoaSBpbiAxOmxlbmd0aChpbnRlcmFjdGlvbl9zaWcpKXsNCiAgZ3JvdXAxIDwtIHVubGlzdChzdHJzcGxpdChpbnRlcmFjdGlvbl9zaWdbaV0sc3BsaXQgPSAiIHZzICIpKVsxXQ0KICBncm91cDIgPC0gdW5saXN0KHN0cnNwbGl0KGludGVyYWN0aW9uX3NpZ1tpXSxzcGxpdCA9ICIgdnMgIikpWzJdDQogIGdyb3VwMiA8LSB1bmxpc3Qoc3Ryc3BsaXQoZ3JvdXAyLHNwbGl0ID0gIiA6ICIpKVsxXQ0KICANCiAgcmVzdWx0X2xpc3QgPC0gYWRvbmlzX3Bvc3RhbmFseXNpcyh4PXBhaXJ3aXNlX2RmLA0KICAgICAgICAgICAgICAgICAgICAgIGZhY3RvcnMgPSBmaWx0X2lsZXVtX21ldGFkYXRhJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAxID0gZ3JvdXAxLA0KICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMiA9IGdyb3VwMikNCiAgcHJpbnQocmVzdWx0X2xpc3QpDQp9DQp9DQpgYGANCg0KKipQQ29BKioNCg0KYGBge3J9DQpwIDwtIHBjYV9wbG90X2N1c3RvbShmaWx0X2lsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfYm94cGxvdHMgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUgPSAiR3JvdXAiLCBzaXplPTMsIHNob3dfbGVnZW5kPUZBTFNFKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX2JldGFbW3Bhc3RlKCJQQ29BIGFpdGNoaXNvbiIsbGV2ZWwsc2VnbWVudCldXSA8LSBwDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpwDQpgYGANCg0KIyMjIyMgQnJheS1DdXJ0aXMgDQoNCipQRVJNQU5PVkEqDQoNCmBgYHtyfQ0KIyBwcmVwYXJpbmcgZGF0YSBmcmFtZQ0KcGFpcndpc2VfZGYgPC0gZmlsdF9pbGV1bV9hc3ZfdGFiICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoIlNlcUlEIikgJT4lIHQoKQ0KDQojIG1haW4gZWZmZWN0DQpwcF9tYWluIDwtIHBhaXJ3aXNlLmFkb25pcyhwYWlyd2lzZV9kZixmaWx0X2lsZXVtX21ldGFkYXRhJEdyb3VwLGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgc2ltLm1ldGhvZCA9ICJicmF5IiwgcC5hZGp1c3QubT0iQkgiKQ0KDQojIGludGVyYWN0aW9uDQpwcF9pbnQgPC0gcGFpcndpc2UuYWRvbmlzKHBhaXJ3aXNlX2RmLGZpbHRfaWxldW1fbWV0YWRhdGEkR3JvdXAsY292YXJpYXRlID0gZmlsdF9pbGV1bV9tZXRhZGF0YSRDb3VudHJ5LCBpbnRlcmFjdGlvbiA9IFRSVUUsIHNpbS5tZXRob2QgPSAiYnJheSIsIHAuYWRqdXN0Lm09IkJIIikNCg0KcHBfZmFjdG9yIDwtIHBwX21haW5bWzFdXQ0KcHBfY292IDwtIHBwX21haW5bWzJdXQ0KcHBfZmFjLmNvdiA8LSBwcF9pbnRbWzNdXQ0KDQpjb2xzIDwtIGMoInBhaXJzIiwiRGYiLCJTdW1zT2ZTcXMiLCAiRi5Nb2RlbCIsIlIyIiwicC52YWx1ZSIsICJwLmFkanVzdGVkIiwgInNpZyIpDQpjb2xuYW1lcyhwcF9mYWN0b3IpIDwtIGNvbHM7IGNvbG5hbWVzKHBwX2NvdikgPC0gY29sczsgY29sbmFtZXMocHBfZmFjLmNvdikgPC0gY29sczsgDQoNCiMgc2F2ZSByYXcgcmVzdWx0cw0Kc3VwcGxlbWVudHNfYmV0YVtbcGFzdGUoImJyYXkiLGxldmVsLHNlZ21lbnQpXV0gPC0gcmJpbmQocHBfZmFjdG9yLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBwX2NvdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcF9mYWMuY292KQ0KDQpgYGANCg0KYGBge3J9DQojIHNlZSB0aGUgcmVzdWx0cw0Ka25pdHI6OmthYmxlKHBwX2ZhY3RvcixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBHUk9VUCBzZXBhcmF0aW9uIikNCmtuaXRyOjprYWJsZShwcF9jb3YsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgQ09VTlRSWSBzZXBhcmF0aW9uIikNCmtuaXRyOjprYWJsZShwcF9mYWMuY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIElOVEVSQUNUSU9OIEdST1VQOkNvdW50cnkiKQ0KYGBgDQoNCkludGVyYWN0aW9uIGNoZWNrDQoNCmBgYHtyfQ0KaW50ZXJhY3Rpb25fc2lnIDwtIHBwX2ZhYy5jb3YkcGFpcnNbcHBfZmFjLmNvdiRwLmFkanVzdGVkIDwgMC4wNV0NCg0KaWYgKGxlbmd0aChpbnRlcmFjdGlvbl9zaWcpPjApew0KZm9yIChpIGluIDE6bGVuZ3RoKGludGVyYWN0aW9uX3NpZykpew0KICBncm91cDEgPC0gdW5saXN0KHN0cnNwbGl0KGludGVyYWN0aW9uX3NpZ1tpXSxzcGxpdCA9ICIgdnMgIikpWzFdDQogIGdyb3VwMiA8LSB1bmxpc3Qoc3Ryc3BsaXQoaW50ZXJhY3Rpb25fc2lnW2ldLHNwbGl0ID0gIiB2cyAiKSlbMl0NCiAgZ3JvdXAyIDwtIHVubGlzdChzdHJzcGxpdChncm91cDIsc3BsaXQgPSAiIDogIikpWzFdDQogIA0KICByZXN1bHRfbGlzdCA8LSBhZG9uaXNfcG9zdGFuYWx5c2lzKHg9cGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycyA9IGZpbHRfaWxldW1fbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9pbGV1bV9tZXRhZGF0YSRDb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICBncm91cDEgPSBncm91cDEsDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAyID0gZ3JvdXAyLA0KICAgICAgICAgICAgICAgICAgICAgIHNpbS5tZXRob2QgPSAnYnJheScpDQogIHByaW50KHJlc3VsdF9saXN0KQ0KfQ0KfQ0KYGBgDQoNCioqUENvQSoqDQoNCmBgYHtyfQ0KcCA8LSBwY2FfcGxvdF9jdXN0b20oZmlsdF9pbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICBtZWFzdXJlID0gImJyYXkiLA0KICAgICAgICAgICAgICAgICAgICAgc2hvd19ib3hwbG90cyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZSA9ICJHcm91cCIsIHNpemU9Mywgc2hvd19sZWdlbmQ9RkFMU0UpDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfYmV0YVtbcGFzdGUoIlBDb0EgYnJheSIsbGV2ZWwsc2VnbWVudCldXSA8LSBwDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpwDQpgYGANCg0KIyMjIyMgSmFjY2FyZA0KDQoqUEVSTUFOT1ZBKg0KDQpgYGB7cn0NCiMgcHJlcGFyaW5nIGRhdGEgZnJhbWUNCnBhaXJ3aXNlX2RmIDwtIGZpbHRfaWxldW1fYXN2X3RhYiAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJTZXFJRCIpICU+JSB0KCkNCg0KIyBtYWluIGVmZmVjdA0KcHBfbWFpbiA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsZmlsdF9pbGV1bV9tZXRhZGF0YSRHcm91cCxjb3ZhcmlhdGUgPSBmaWx0X2lsZXVtX21ldGFkYXRhJENvdW50cnksIHNpbS5tZXRob2QgPSAiamFjY2FyZCIsIHAuYWRqdXN0Lm09IkJIIikNCg0KIyBpbnRlcmFjdGlvbg0KcHBfaW50IDwtIHBhaXJ3aXNlLmFkb25pcyhwYWlyd2lzZV9kZixmaWx0X2lsZXVtX21ldGFkYXRhJEdyb3VwLGNvdmFyaWF0ZSA9IGZpbHRfaWxldW1fbWV0YWRhdGEkQ291bnRyeSwgaW50ZXJhY3Rpb24gPSBUUlVFLCBzaW0ubWV0aG9kID0gImphY2NhcmQiLCBwLmFkanVzdC5tPSJCSCIpDQoNCnBwX2ZhY3RvciA8LSBwcF9tYWluW1sxXV0NCnBwX2NvdiA8LSBwcF9tYWluW1syXV0NCnBwX2ZhYy5jb3YgPC0gcHBfaW50W1szXV0NCg0KY29scyA8LSBjKCJwYWlycyIsIkRmIiwiU3Vtc09mU3FzIiwgIkYuTW9kZWwiLCJSMiIsInAudmFsdWUiLCAicC5hZGp1c3RlZCIsICJzaWciKQ0KY29sbmFtZXMocHBfZmFjdG9yKSA8LSBjb2xzOyBjb2xuYW1lcyhwcF9jb3YpIDwtIGNvbHM7IGNvbG5hbWVzKHBwX2ZhYy5jb3YpIDwtIGNvbHM7IA0KDQojIHNhdmUgcmF3IHJlc3VsdHMNCnN1cHBsZW1lbnRzX2JldGFbW3Bhc3RlKCJqYWNjYXJkIixsZXZlbCxzZWdtZW50KV1dIDwtIHJiaW5kKHBwX2ZhY3RvciwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcF9jb3YsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHBfZmFjLmNvdikNCmBgYA0KDQpgYGB7cn0NCiMgc2VlIHRoZSByZXN1bHRzDQprbml0cjo6a2FibGUocHBfZmFjdG9yLGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIEdST1VQIHNlcGFyYXRpb24iKQ0Ka25pdHI6OmthYmxlKHBwX2NvdixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBDT1VOVFJZIHNlcGFyYXRpb24iKQ0Ka25pdHI6OmthYmxlKHBwX2ZhYy5jb3YsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgSU5URVJBQ1RJT04gR1JPVVA6Q291bnRyeSIpDQpgYGANCg0KSW50ZXJhY3Rpb24gY2hlY2sNCg0KYGBge3J9DQppbnRlcmFjdGlvbl9zaWcgPC0gcHBfZmFjLmNvdiRwYWlyc1twcF9mYWMuY292JHAuYWRqdXN0ZWQgPCAwLjA1XQ0KDQppZiAobGVuZ3RoKGludGVyYWN0aW9uX3NpZyk+MCl7DQpmb3IgKGkgaW4gMTpsZW5ndGgoaW50ZXJhY3Rpb25fc2lnKSl7DQogIGdyb3VwMSA8LSB1bmxpc3Qoc3Ryc3BsaXQoaW50ZXJhY3Rpb25fc2lnW2ldLHNwbGl0ID0gIiB2cyAiKSlbMV0NCiAgZ3JvdXAyIDwtIHVubGlzdChzdHJzcGxpdChpbnRlcmFjdGlvbl9zaWdbaV0sc3BsaXQgPSAiIHZzICIpKVsyXQ0KICBncm91cDIgPC0gdW5saXN0KHN0cnNwbGl0KGdyb3VwMixzcGxpdCA9ICIgOiAiKSlbMV0NCiAgDQogIHJlc3VsdF9saXN0IDwtIGFkb25pc19wb3N0YW5hbHlzaXMoeD1wYWlyd2lzZV9kZiwNCiAgICAgICAgICAgICAgICAgICAgICBmYWN0b3JzID0gZmlsdF9pbGV1bV9tZXRhZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGUgPSBmaWx0X2lsZXVtX21ldGFkYXRhJENvdW50cnksIA0KICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMSA9IGdyb3VwMSwNCiAgICAgICAgICAgICAgICAgICAgICBncm91cDIgPSBncm91cDIsDQogICAgICAgICAgICAgICAgICAgICAgc2ltLm1ldGhvZCA9ICdqYWNjYXJkJykNCiAgcHJpbnQocmVzdWx0X2xpc3QpDQp9DQp9DQpgYGANCg0KKipQQ29BKioNCg0KYGBge3J9DQpwIDwtIHBjYV9wbG90X2N1c3RvbShmaWx0X2lsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPSAiamFjY2FyZCIsDQogICAgICAgICAgICAgICAgICAgICBzaG93X2JveHBsb3RzID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlID0gIkdyb3VwIiwgc2l6ZT0zLCBzaG93X2xlZ2VuZD1GQUxTRSkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiUENvQSBqYWNjYXJkIixsZXZlbCxzZWdtZW50KV1dIDwtIHANCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnANCmBgYA0KDQojIyMjIFNhdmluZyByZXN1bHRzDQoNCmBgYHtyfQ0Kd3JpdGUueGxzeChzdXBwbGVtZW50c19iZXRhWyFncmVwbCgiUENvQSIsbmFtZXMoc3VwcGxlbWVudHNfYmV0YSkpXSwNCiAgICAgICAgICAgZmlsZSA9IGZpbGUucGF0aChwYXRoLA0KICAgICAgICAgICBwYXN0ZTAoInN1cHBsZW1lbnRzX2JldGFfZGl2ZXJzaXR5XyIsIHNlZ21lbnQsIi54bHN4IikpKQ0KYGBgDQoNCiMjIFVuaXZhcmlhdGUgQW5hbHlzaXMNCg0KIyMjIE1haW4gLSBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpgYGB7cn0NCiMgbmVlZGVkIHBhdGhzDQpwYXRoID0gIi4uL3Jlc3VsdHMvUTIvdW5pdmFyaWF0ZV9hbmFseXNpcyINCnBhdGhfbWFhc2xpbj1maWxlLnBhdGgoIi4uL2ludGVybWVkaWF0ZV9maWxlcy9tYWFzbGluL1EyIixsZXZlbCkNCmBgYA0KDQpgYGB7cn0NCiMgdmFyaWFibGVzDQpyYXdfbGluZGFfcmVzdWx0c19nZW51cyA8LSBsaXN0KCk7DQpyYXdfbGluZGFfcmVzdWx0c19nZW51c1tbc2VnbWVudF1dIDwtIGxpc3QoKQ0KbGluZGFfcmVzdWx0c19nZW51cyA8LSBsaXN0KCk7IA0KbGluZGFfcmVzdWx0c19nZW51c1tbc2VnbWVudF1dIDwtIGxpc3QoKQ0KDQojIGNvdW50cnkgYW5kIGludGVyYWN0aW9uIHByb2JsZW1zDQpsaXN0X2NvdW50cnlfdW5pb24gPC0gbGlzdCgpDQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gbGlzdCgpDQpsaXN0X3Zlbm5zIDwtIGxpc3QoKQ0KdW5pX3N0YXRpc3RpY3MgPC0gbGlzdCgpDQoNCiMgd29ya2Jvb2sgZm9yIGZpbmFsIGRmDQp3YiA8LSBjcmVhdGVXb3JrYm9vaygpDQoNCiMgclBTQyBlZmZlY3QNCnJwc2NfZWZmZWN0IDwtIGxpc3QoKQ0KYGBgDQoNCkFnZ3JlZ2F0ZSB0YXhhDQoNCmBgYHtyfQ0KZ2VudXNfZGF0YSA8LSBhZ2dyZWdhdGVfdGF4YShpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4b25vbWljX2xldmVsID0gbGV2ZWwpDQoNCmlsZXVtX2dlbnVzX3RhYiA8LSBnZW51c19kYXRhW1sxXV0NCmlsZXVtX2dlbnVzX3RheGFfdGFiIDwtIGdlbnVzX2RhdGFbWzJdXQ0KDQppbGV1bV9nZW51c19hc3ZfdGF4YV90YWIgPC0gY3JlYXRlX2Fzdl90YXhhX3RhYmxlKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIpDQpgYGANCg0KIyMjIyByUFNDIHZzIG5vbi1yUFNDDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJyUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQojIyMjIyBsaW5EQQ0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpsaW5kYV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9pbGV1bV91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfaWxldW1fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2lsZXVtX3VuaV9kYXRhLCANCiAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZm9ybXVsYSA9ICd+IEdyb3VwICogQ291bnRyeScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpncm91cDEgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSkNCmdyb3VwMiA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgLCAiLGdyb3VwWzJdLCAiIC0gQ1ogdnMgTk8iKSANCmdyb3VwMyA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdLCAiOkNvdW50cnlOTyIpDQoNCmZvciAoZ3JwIGluIGMoZ3JvdXAxLGdyb3VwMixncm91cDMpKXsNCiAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgcmF3bGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQogIA0KICBsaW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIGxpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV90YXhhKQ0KfQ0KDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cDEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoY29tcGFyaXNvbl9uYW1lKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKSANCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCmBgYA0KDQojIyMjIyBNYUFzTGluMg0KDQpgYGB7ciwgZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJyxtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQpmaXRfZGF0YSA9IE1hYXNsaW4yKA0KICAgIGlucHV0X2RhdGEgPSBmaWx0X2lsZXVtX3VuaV9kYXRhLCANCiAgICBpbnB1dF9tZXRhZGF0YSA9IGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLCBtaW5fYWJ1bmRhbmNlID0gMCwNCiAgICBtaW5fcHJldmFsZW5jZSA9IDAsbWluX3ZhcmlhbmNlID0gMCwNCiAgICBvdXRwdXQgPSBmaWxlLnBhdGgocGF0aF9tYWFzbGluLGdyb3VwMSksIG1heF9zaWduaWZpY2FuY2UgPSAwLjA1LA0KICAgIGZpeGVkX2VmZmVjdHMgPSBjKCdHcm91cCcsICdDb3VudHJ5JyksY29ycmVjdGlvbiA9ICJCSCIpDQoNCmBgYA0KDQpgYGB7cn0NCnZvbGNhbm8xIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfaWxldW1fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKGNvbXBhcmlzb25fbmFtZSkNCg0Kdm9sY2FubzIgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9pbGV1bV91bmlfdGF4YSx2YXJpYWJsZT0iQ291bnRyeSIpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQp2b2xjYW5vDQpgYGANCg0KIyMjIyMgR3JvdXAgLSBJbnRlcnNlY3Rpb24NCg0KYGBge3J9DQppbnRlcnNlY3Rpb25fcmVzdWx0cyA8LSBncm91cF9pbnRlcnNlY3Rpb24oZ3JvdXAsIGxpc3RfaW50ZXJzZWN0aW9ucywgbGlzdF92ZW5ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50ID0gc2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1sxXV0NCmxpc3RfdmVubnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzJdXQ0KdmVubiA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbM11dDQoNCiMgc2hvdyB0aGUgcmVzdWx0cw0KdmVubg0KYGBgDQoNCiMjIyMjIENvdW50cnkgLSBVbmlvbg0KDQpgYGB7cixldmFsPUZBTFNFfQ0KbGlzdF9jb3VudHJ5X3VuaW9uIDwtIGNvdW50cnlfdW5pb24oZ3JvdXAsbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCiMjIyMjIEludGVyYWN0aW9uIGVmZmVjdA0KDQpgYGB7cn0NCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQgPC0gY291bnRyeV9pbnRlcmFjdGlvbihncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQojIHNlZSB0aGUgcmVzdWx0DQojIyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBlZmZlY3QNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzFdXQ0KDQojIyByZXN1bHRzIGZvciBjemVjaCBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzJdXQ0KDQojIyByZXN1bHRzIGZvciBub3J3ZWdpYW4gY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1szXV0NCmBgYA0KDQpSZW1vdmluZyBwcm9ibGVtYXRpYyB0YXhhDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIHJlbW92aW5nX2ludGVyYWN0aW9uX3Byb2JsZW1zKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQojIyMjIyBCYXNpYyBzdGF0aXN0aWNzDQoNCmBgYHtyfQ0KdW5pX2RmIDwtICBtZXJnZShiYXNpY191bml2YXJpYXRlX3N0YXRpc3RpY3MobGluZGFfZGF0YSxncm91cCksDQogICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dyb3VwMV1dLA0KICAgICAgICAgICAgICAgICBieT0iU2VxSUQiLGFsbD1UUlVFKQ0KDQp1bmlfZGZbWyJmaW5hbF9zaWciXV0gPC0gdW5pX2RmJFNlcUlEICVpbiUgbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLGNvbXBhcmlzb25fbmFtZSldXVtbIlNlcUlEIl1dDQp1bmlfc3RhdGlzdGljc1tbc2VnbWVudF1dW1twYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpXV0gPC0gdW5pX2RmDQoNCiMgZm9yIGNvbXBhcmlzb24NCm5ld19uYW1lIDwtIGNvbXBhcmlzb25fbmFtZQ0KYWRkV29ya3NoZWV0KHdiLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YSh3Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIHJQU0MgdnMgaGVhbHRoeQ0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoImhlYWx0aHkiLCJyUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQojIyMjIyBsaW5EQQ0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpsaW5kYV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9pbGV1bV91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfaWxldW1fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2lsZXVtX3VuaV9kYXRhLCANCiAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZm9ybXVsYSA9ICd+IEdyb3VwICogQ291bnRyeScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpncm91cDEgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSkNCmdyb3VwMiA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgLCAiLGdyb3VwWzJdLCAiIC0gQ1ogdnMgTk8iKSANCmdyb3VwMyA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdLCAiOkNvdW50cnlOTyIpDQoNCmZvciAoZ3JwIGluIGMoZ3JvdXAxLGdyb3VwMixncm91cDMpKXsNCiAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgcmF3bGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQogIA0KICBsaW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIGxpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV90YXhhKQ0KfQ0KDQojIHN1bW1hcnkgc3RhdGlzdGljcw0KIyByYXdfbGluZGFfcmVzdWx0c19nZW51cyA8LSBiaW5vbWlhbF9zdGF0aXN0aWNzKGZpbHRfaWxldW1fdW5pX2RhdGEsICAgICAgICAgICAgIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwPWdyb3VwLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQgPSAidGVybWluYWxfaWxldW0iKQ0KDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cDEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoY29tcGFyaXNvbl9uYW1lKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKSANCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCmBgYA0KDQojIyMjIyBNYUFzTGluMg0KDQpgYGB7ciwgZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJyxtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQpmaXRfZGF0YSA9IE1hYXNsaW4yKA0KICAgIGlucHV0X2RhdGEgPSBmaWx0X2lsZXVtX3VuaV9kYXRhLCANCiAgICBpbnB1dF9tZXRhZGF0YSA9IGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLCBtaW5fYWJ1bmRhbmNlID0gMCwNCiAgICBtaW5fcHJldmFsZW5jZSA9IDAsbWluX3ZhcmlhbmNlID0gMCwNCiAgICBvdXRwdXQgPSBmaWxlLnBhdGgocGF0aF9tYWFzbGluLGdyb3VwMSksIG1heF9zaWduaWZpY2FuY2UgPSAwLjA1LA0KICAgIGZpeGVkX2VmZmVjdHMgPSBjKCdHcm91cCcsICdDb3VudHJ5JyksY29ycmVjdGlvbiA9ICJCSCIpDQoNCmBgYA0KDQpgYGB7cn0NCnZvbGNhbm8xIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfaWxldW1fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKGNvbXBhcmlzb25fbmFtZSkNCg0Kdm9sY2FubzIgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9pbGV1bV91bmlfdGF4YSx2YXJpYWJsZT0iQ291bnRyeSIpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQp2b2xjYW5vDQpgYGANCg0KIyMjIyMgR3JvdXAgLSBJbnRlcnNlY3Rpb24NCg0KYGBge3J9DQppbnRlcnNlY3Rpb25fcmVzdWx0cyA8LSBncm91cF9pbnRlcnNlY3Rpb24oZ3JvdXAsIGxpc3RfaW50ZXJzZWN0aW9ucywgbGlzdF92ZW5ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50ID0gc2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1sxXV0NCmxpc3RfdmVubnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzJdXQ0KdmVubiA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbM11dDQoNCiMgc2hvdyB0aGUgcmVzdWx0cw0KdmVubg0KYGBgDQoNCiMjIyMjIENvdW50cnkgLSBVbmlvbg0KDQpgYGB7cixldmFsPUZBTFNFfQ0KbGlzdF9jb3VudHJ5X3VuaW9uIDwtIGNvdW50cnlfdW5pb24oZ3JvdXAsbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCiMjIyMjIEludGVyYWN0aW9uIGVmZmVjdA0KDQpgYGB7cn0NCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQgPC0gY291bnRyeV9pbnRlcmFjdGlvbihncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQojIHNlZSB0aGUgcmVzdWx0DQojIyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBlZmZlY3QNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzFdXQ0KDQojIyByZXN1bHRzIGZvciBjemVjaCBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzJdXQ0KDQojIyByZXN1bHRzIGZvciBub3J3ZWdpYW4gY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1szXV0NCmBgYA0KDQpSZW1vdmluZyBwcm9ibGVtYXRpYyB0YXhhDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIHJlbW92aW5nX2ludGVyYWN0aW9uX3Byb2JsZW1zKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQojIyMjIyBCYXNpYyBzdGF0aXN0aWNzDQoNCmBgYHtyfQ0KdW5pX2RmIDwtICBtZXJnZShiYXNpY191bml2YXJpYXRlX3N0YXRpc3RpY3MobGluZGFfZGF0YSxncm91cCksDQogICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dyb3VwMV1dLA0KICAgICAgICAgICAgICAgICBieT0iU2VxSUQiLGFsbD1UUlVFKQ0KDQp1bmlfZGZbWyJmaW5hbF9zaWciXV0gPC0gdW5pX2RmJFNlcUlEICVpbiUgbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLGNvbXBhcmlzb25fbmFtZSldXVtbIlNlcUlEIl1dDQp1bmlfc3RhdGlzdGljc1tbc2VnbWVudF1dW1twYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpXV0gPC0gdW5pX2RmDQoNCiMgZm9yIGNvbXBhcmlzb24NCm5ld19uYW1lIDwtIGNvbXBhcmlzb25fbmFtZQ0KYWRkV29ya3NoZWV0KHdiLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YSh3Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIG5vbi1yUFNDIHZzIGhlYWx0aHkNCg0KYGBge3J9DQpncm91cCA8LSBjKCJoZWFsdGh5Iiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCiMjIyMjIGxpbkRBDQoNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmxpbmRhX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJsaW5EQSIpDQoNCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gbGluZGFfZGF0YVtbMV1dDQpmaWx0X2lsZXVtX3VuaV90YXhhIDwtIGxpbmRhX2RhdGFbWzJdXQ0KZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEgPC0gbGluZGFfZGF0YVtbM11dDQoNCiMgZml0IHRoZSBtb2RlbA0KbGluZGEub2JqIDwtIGxpbmRhKGZpbHRfaWxldW1fdW5pX2RhdGEsIA0KICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLCANCiAgICAgICAgICAgICAgICAgICBmb3JtdWxhID0gJ34gR3JvdXAgKiBDb3VudHJ5JykNCg0KbGluZGEub3V0cHV0IDwtIGxpbmRhLm9iaiRvdXRwdXQNCmxpbmRhLm91dHB1dCA8LSBsaW5kYV9yZW5hbWluZyhsaW5kYS5vdXRwdXQsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCmdyb3VwMSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdKQ0KZ3JvdXAyIDwtIHBhc3RlMChncm91cFsxXSwgIiAsICIsZ3JvdXBbMl0sICIgLSBDWiB2cyBOTyIpIA0KZ3JvdXAzIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0sICI6Q291bnRyeU5PIikNCg0KZm9yIChncnAgaW4gYyhncm91cDEsZ3JvdXAyLGdyb3VwMykpew0KICByYXdfbGluZGFfcmVzdWx0c19nZW51c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICByYXdsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfdGF4YSkNCiAgDQogIGxpbmRhX3Jlc3VsdHNfZ2VudXNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgbGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQp9DQoNCiMgc3VtbWFyeSBzdGF0aXN0aWNzDQojIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzIDwtIGJpbm9taWFsX3N0YXRpc3RpY3MoZmlsdF9pbGV1bV91bmlfZGF0YSwgICAgICAgICAgICAgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXA9Z3JvdXAsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXMsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9ICJ0ZXJtaW5hbF9pbGV1bSIpDQoNCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCiMgdm9sY2FubyBwbG90DQp2b2xjYW5vXzEgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShjb21wYXJpc29uX25hbWUpDQoNCnZvbGNhbm9fMiAgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfaWxldW1fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpIA0KDQp2b2xjYW5vXzMgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfaWxldW1fdW5pX3RheGEpICsNCiAgICAgICAgICAgIGdndGl0bGUoIkludGVyYWN0aW9uIikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2Fub18xLHZvbGNhbm9fMix2b2xjYW5vXzMsIG5jb2w9MykNCg0KYGBgDQoNCiMjIyMjIE1hQXNMaW4yDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmZpdF9kYXRhID0gTWFhc2xpbjIoDQogICAgaW5wdXRfZGF0YSA9IGZpbHRfaWxldW1fdW5pX2RhdGEsIA0KICAgIGlucHV0X21ldGFkYXRhID0gZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEsIG1pbl9hYnVuZGFuY2UgPSAwLA0KICAgIG1pbl9wcmV2YWxlbmNlID0gMCxtaW5fdmFyaWFuY2UgPSAwLA0KICAgIG91dHB1dCA9IGZpbGUucGF0aChwYXRoX21hYXNsaW4sZ3JvdXAxKSwgbWF4X3NpZ25pZmljYW5jZSA9IDAuMDUsDQogICAgZml4ZWRfZWZmZWN0cyA9IGMoJ0dyb3VwJywgJ0NvdW50cnknKSxjb3JyZWN0aW9uID0gIkJIIikNCg0KYGBgDQoNCmBgYHtyfQ0Kdm9sY2FubzEgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoY29tcGFyaXNvbl9uYW1lKQ0KDQp2b2xjYW5vMiA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2lsZXVtX3VuaV90YXhhLHZhcmlhYmxlPSJDb3VudHJ5IikgKyANCiAgICAgICAgICAgIGdndGl0bGUoIkNvdW50cnkgZWZmZWN0IikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2FubzEsdm9sY2FubzIsIG5jb2w9MikNCnZvbGNhbm8NCmBgYA0KDQojIyMjIyBHcm91cCAtIEludGVyc2VjdGlvbg0KDQpgYGB7cn0NCmludGVyc2VjdGlvbl9yZXN1bHRzIDwtIGdyb3VwX2ludGVyc2VjdGlvbihncm91cCwgbGlzdF9pbnRlcnNlY3Rpb25zLCBsaXN0X3Zlbm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQgPSBzZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzFdXQ0KbGlzdF92ZW5ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMl1dDQp2ZW5uIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1szXV0NCg0KIyBzaG93IHRoZSByZXN1bHRzDQp2ZW5uDQpgYGANCg0KIyMjIyMgQ291bnRyeSAtIFVuaW9uDQoNCmBgYHtyLGV2YWw9RkFMU0V9DQpsaXN0X2NvdW50cnlfdW5pb24gPC0gY291bnRyeV91bmlvbihncm91cCxsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIyMjIyMgSW50ZXJhY3Rpb24gZWZmZWN0DQoNCmBgYHtyfQ0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCA8LSBjb3VudHJ5X2ludGVyYWN0aW9uKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCiMgc2VlIHRoZSByZXN1bHQNCiMjIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGVmZmVjdA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMV1dDQoNCiMjIHJlc3VsdHMgZm9yIGN6ZWNoIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMl1dDQoNCiMjIHJlc3VsdHMgZm9yIG5vcndlZ2lhbiBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzNdXQ0KYGBgDQoNClJlbW92aW5nIHByb2JsZW1hdGljIHRheGENCg0KYGBge3J9DQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gcmVtb3ZpbmdfaW50ZXJhY3Rpb25fcHJvYmxlbXMoZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCiMjIyMjIEJhc2ljIHN0YXRpc3RpY3MNCg0KYGBge3J9DQp1bmlfZGYgPC0gIG1lcmdlKGJhc2ljX3VuaXZhcmlhdGVfc3RhdGlzdGljcyhsaW5kYV9kYXRhLGdyb3VwKSwNCiAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXNbW3NlZ21lbnRdXVtbZ3JvdXAxXV0sDQogICAgICAgICAgICAgICAgIGJ5PSJTZXFJRCIsYWxsPVRSVUUpDQoNCnVuaV9kZltbImZpbmFsX3NpZyJdXSA8LSB1bmlfZGYkU2VxSUQgJWluJSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dW1siU2VxSUQiXV0NCnVuaV9zdGF0aXN0aWNzW1tzZWdtZW50XV1bW3Bhc3RlKGxldmVsLGNvbXBhcmlzb25fbmFtZSldXSA8LSB1bmlfZGYNCg0KIyBmb3IgY29tcGFyaXNvbg0KbmV3X25hbWUgPC0gY29tcGFyaXNvbl9uYW1lDQphZGRXb3Jrc2hlZXQod2IsIHNoZWV0TmFtZSA9IG5ld19uYW1lKQ0Kd3JpdGVEYXRhKHdiLCBzaGVldCA9IG5ld19uYW1lLCB1bmlfZGYsIHJvd05hbWVzPUZBTFNFKQ0KYGBgDQoNCiMjIyMgVmlzdWFsaXphdGlvbg0KDQpIZWF0bWFwIHZpc3VhbGl6aW5nIHRoZSBsaW5EQSdzIGxvZ0ZvbGRDaGFuZ2UgZm9yIHRheGEgd2l0aCBwIFw8IDAuMS4NCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xNywgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KbGlzdF9oZWF0bWFwIDwtIGxpc3RfaW50ZXJzZWN0aW9uc1tncmVwKHBhc3RlKHNlZ21lbnQsbGV2ZWwpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzKGxpc3RfaW50ZXJzZWN0aW9ucyksdmFsdWU9VFJVRSldDQoNCnBfaGVhdG1hcF9saW5kYSA8LSBoZWF0bWFwX2xpbmRhKGxpc3RfaGVhdG1hcCxpbGV1bV90YXhhX3RhYikNCnBfaGVhdG1hcF9saW5kYQ0KYGBgDQoNCkRvdCBoZWF0bWFwDQoNCmBgYHtyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD0xMCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KZG90aGVhdG1hcF9saW5kYSA8LSBkb3RfaGVhdG1hcF9saW5kYSgNCiAgbGlzdF9oZWF0bWFwLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmlfc3RhdGlzdGljcyR0ZXJtaW5hbF9pbGV1bVtncmVwbChsZXZlbCxuYW1lcyh1bmlfc3RhdGlzdGljcyR0ZXJtaW5hbF9pbGV1bSkpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIpICsgeGxhYigiIikgKyB5bGFiKCIiKQ0KZG90aGVhdG1hcF9saW5kYQ0KYGBgDQoNCioqSG9yaXpvbnRhbCBiYXIgcGxvdCoqDQoNCmBgYHtyfQ0KcF9wcmV2YWxlbmNlIDwtIGhvcml6b250YWxfYmFycGxvdCh3Yix0YXhhPWxldmVscyhkb3RoZWF0bWFwX2xpbmRhJGRhdGEkU2VxSUQpKQ0KYGBgDQoNCg0KYGBge3J9DQpwX3ByZXZhbGVuY2VfZmluYWwgPC0gZ2dhcnJhbmdlKHBfcHJldmFsZW5jZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyB0aGVtZV9taW5pbWFsKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSAyLGhlaWdodHMgPSBjKDEsMC4wODUpKQ0KcCA8LSBnZ2FycmFuZ2UoZG90aGVhdG1hcF9saW5kYSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikscF9wcmV2YWxlbmNlX2ZpbmFsLG5jb2w9Mix3aWR0aHMgPSBjKDEsMC4zKSkNCnANCg0KZG90X2hlYXRtYXBfaWxldW0gPC0gcA0KYGBgDQoNCmBgYHtyLHJlc3VsdHM9J2hpZGUnfQ0KcGRmKCIuLi9maWd1cmVzL1EyL2RvdHBsb3RfdGVybWluYWxfaWxldW0ucGRmIiwNCiAgICBoZWlnaHQgPTEwLHdpZHRoID0gNCkNCnANCmRldi5vZmYoKQ0KYGBgDQoNCg0KIyMjIyByUFNDIGVmZmVjdA0KDQoqKnByZV9MVHggdnMgSGVhbHRoeSBhbmQgUG9zdF9MVHggdnMgSGVhbHRoeSBpbnRlcnNlY3Rpb24qKg0KDQoNCmBgYHtyfQ0KQSA8LSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsImhlYWx0aHkgdnMgclBTQyIpXV0NCkIgPC0gbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLCJoZWFsdGh5IHZzIG5vbi1yUFNDIildXQ0KZGYgPC0gQVshKEEkU2VxSUQgJWluJSBCJFNlcUlEKSxdDQoNCg0KcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0gPC0gZGYNCiAgDQojIHNlZSB0aGUgcmVzdWx0cw0KcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0gDQpgYGANCg0KIyMjIyBTYXZpbmcgcmVzdWx0cw0KDQpgYGB7cn0NCiMgQUxMIERBVEENCnNhdmVXb3JrYm9vayh3YixmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInVuaV9hbmFseXNpc193Yl8iLHNlZ21lbnQsIi54bHN4IikpLA0KICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IFRSVUUpDQoNCiMgUFNDIGVmZmVjdA0Kd3JpdGUueGxzeChycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSxmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInJwc2NfZWZmZWN0XyIsc2VnbWVudCwiLnhsc3giKSkpDQoNCiMgU0lHTklGSUNBTlQgdGF4YQ0KDQp3cml0ZS54bHN4KGxpc3RfaW50ZXJzZWN0aW9uc1tncmVwbChzZWdtZW50LG5hbWVzKGxpc3RfaW50ZXJzZWN0aW9ucykpXSAlPiUNCiAgICAgICAgICAgIGBuYW1lczwtYChnc3ViKHNlZ21lbnQsICIiLCBuYW1lcygNCiAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zW2dyZXBsKHNlZ21lbnQsbmFtZXMobGlzdF9pbnRlcnNlY3Rpb25zKSldKSkpLA0KICAgICAgICAgICBmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInNpZ25pZmljYW50X3RheGFfIixzZWdtZW50LCIueGxzeCIpKSkNCmBgYA0KDQoNCiMjIyBTdXBwbGVtZW50YXJ5IEFuYWx5c2lzDQoNCmBgYHtyfQ0Kc3VwcGxlbWVudHNfdW5pIDwtIGxpc3QoKQ0Kc3VwcGxlbWVudHNfd2IgPC0gY3JlYXRlV29ya2Jvb2soKQ0KYGBgDQoNCiMjIyMgQVNWIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9IkFTViINCmBgYA0KDQpgYGB7cn0NCnBhdGhfbWFhc2xpbj0iLi4vaW50ZXJtZWRpYXRlX2ZpbGVzL21hYXNsaW4vUTIvQVNWLyINCmBgYA0KDQpgYGB7cn0NCnJhd19saW5kYV9yZXN1bHRzIDwtIGxpc3QoKTsNCnJhd19saW5kYV9yZXN1bHRzW1tzZWdtZW50XV0gPC0gbGlzdCgpDQpsaW5kYV9yZXN1bHRzIDwtIGxpc3QoKTsgDQpsaW5kYV9yZXN1bHRzW1tzZWdtZW50XV0gPC0gbGlzdCgpDQpgYGANCg0KIyMjIyMgclBTQyB2cyBub24tclBTQw0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KKipsaW5EQSoqDQoNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmxpbmRhX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9pbGV1bV91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfaWxldW1fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2lsZXVtX3VuaV9kYXRhLCANCiAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZm9ybXVsYSA9ICd+IEdyb3VwICogQ291bnRyeScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpncm91cDEgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSkNCmdyb3VwMiA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgLCAiLGdyb3VwWzJdLCAiIC0gQ1ogdnMgTk8iKSANCmdyb3VwMyA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdLCAiOkNvdW50cnlOTyIpDQoNCmZvciAoZ3JwIGluIGMoZ3JvdXAxLGdyb3VwMixncm91cDMpKXsNCiAgcmF3X2xpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgcmF3bGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQogIA0KICBsaW5kYV9yZXN1bHRzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIGxpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV90YXhhKQ0KfQ0KDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cDEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoY29tcGFyaXNvbl9uYW1lKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKSANCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCmBgYA0KDQogTWFBc0xpbjINCg0KYGBge3IsIGVjaG89RkFMU0UscmVzdWx0cz0naGlkZScsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KZml0X2RhdGEgPSBNYWFzbGluMigNCiAgICBpbnB1dF9kYXRhID0gZmlsdF9pbGV1bV91bmlfZGF0YSwgDQogICAgaW5wdXRfbWV0YWRhdGEgPSBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwgbWluX2FidW5kYW5jZSA9IDAsDQogICAgbWluX3ByZXZhbGVuY2UgPSAwLG1pbl92YXJpYW5jZSA9IDAsDQogICAgb3V0cHV0ID0gZmlsZS5wYXRoKHBhdGhfbWFhc2xpbixncm91cDEpLCBtYXhfc2lnbmlmaWNhbmNlID0gMC4wNSwNCiAgICBmaXhlZF9lZmZlY3RzID0gYygnR3JvdXAnLCAnQ291bnRyeScpLGNvcnJlY3Rpb24gPSAiQkgiKQ0KDQpgYGANCg0KYGBge3J9DQp2b2xjYW5vMSA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShjb21wYXJpc29uX25hbWUpDQoNCnZvbGNhbm8yIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfaWxldW1fdW5pX3RheGEsdmFyaWFibGU9IkNvdW50cnkiKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vMSx2b2xjYW5vMiwgbmNvbD0yKQ0Kdm9sY2Fubw0KYGBgDQoNCiBHcm91cCAtIEludGVyc2VjdGlvbg0KDQpgYGB7cn0NCmludGVyc2VjdGlvbl9yZXN1bHRzIDwtIGdyb3VwX2ludGVyc2VjdGlvbihncm91cCwgbGlzdF9pbnRlcnNlY3Rpb25zLCBsaXN0X3Zlbm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQgPSBzZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzFdXQ0KbGlzdF92ZW5ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMl1dDQp2ZW5uIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1szXV0NCg0KIyBzaG93IHRoZSByZXN1bHRzDQp2ZW5uDQpgYGANCg0KIENvdW50cnkgLSBVbmlvbg0KDQpgYGB7cixldmFsPUZBTFNFfQ0KbGlzdF9jb3VudHJ5X3VuaW9uIDwtIGNvdW50cnlfdW5pb24oZ3JvdXAsbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCiBJbnRlcmFjdGlvbiBlZmZlY3QNCg0KYGBge3J9DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50IDwtIGNvdW50cnlfaW50ZXJhY3Rpb24oZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KIyBzZWUgdGhlIHJlc3VsdA0KIyMgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gZWZmZWN0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1sxXV0NCg0KIyMgcmVzdWx0cyBmb3IgY3plY2ggY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1syXV0NCg0KIyMgcmVzdWx0cyBmb3Igbm9yd2VnaWFuIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbM11dDQpgYGANCg0KUmVtb3ZpbmcgcHJvYmxlbWF0aWMgdGF4YQ0KDQpgYGB7cn0NCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSByZW1vdmluZ19pbnRlcmFjdGlvbl9wcm9ibGVtcyhncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIEJhc2ljIHN0YXRpc3RpY3MNCg0KYGBge3J9DQp1bmlfZGYgPC0gIG1lcmdlKGJhc2ljX3VuaXZhcmlhdGVfc3RhdGlzdGljcyhsaW5kYV9kYXRhLGdyb3VwKSwNCiAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JvdXAxXV0sDQogICAgICAgICAgICAgICAgIGJ5PSJTZXFJRCIsYWxsPVRSVUUpDQoNCnVuaV9kZltbImZpbmFsX3NpZyJdXSA8LSB1bmlfZGYkU2VxSUQgJWluJSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dW1siU2VxSUQiXV0NCnVuaV9zdGF0aXN0aWNzW1tzZWdtZW50XV1bW3Bhc3RlKGxldmVsLGNvbXBhcmlzb25fbmFtZSldXSA8LSB1bmlfZGYNCg0KIyBmb3IgY29tcGFyaXNvbg0KbmV3X25hbWUgPC0gcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKQ0KYWRkV29ya3NoZWV0KHN1cHBsZW1lbnRzX3diLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YShzdXBwbGVtZW50c193Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIyByUFNDIHZzIGhlYWx0aHkNCg0KYGBge3J9DQpncm91cCA8LSBjKCJoZWFsdGh5IiwiclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KIGxpbkRBDQoNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmxpbmRhX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9pbGV1bV91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfaWxldW1fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2lsZXVtX3VuaV9kYXRhLCANCiAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZm9ybXVsYSA9ICd+IEdyb3VwICogQ291bnRyeScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpncm91cDEgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSkNCmdyb3VwMiA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgLCAiLGdyb3VwWzJdLCAiIC0gQ1ogdnMgTk8iKSANCmdyb3VwMyA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdLCAiOkNvdW50cnlOTyIpDQoNCmZvciAoZ3JwIGluIGMoZ3JvdXAxLGdyb3VwMixncm91cDMpKXsNCiAgcmF3X2xpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgcmF3bGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQogIA0KICBsaW5kYV9yZXN1bHRzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIGxpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV90YXhhKQ0KfQ0KDQojIHN1bW1hcnkgc3RhdGlzdGljcw0KIyByYXdfbGluZGFfcmVzdWx0c19nZW51cyA8LSBiaW5vbWlhbF9zdGF0aXN0aWNzKGZpbHRfaWxldW1fdW5pX2RhdGEsICAgICAgICAgICAgIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwPWdyb3VwLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQgPSAidGVybWluYWxfaWxldW0iKQ0KDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cDEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoY29tcGFyaXNvbl9uYW1lKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKSANCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCmBgYA0KDQogTWFBc0xpbjINCg0KYGBge3IsIGVjaG89RkFMU0UscmVzdWx0cz0naGlkZScsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KZml0X2RhdGEgPSBNYWFzbGluMigNCiAgICBpbnB1dF9kYXRhID0gZmlsdF9pbGV1bV91bmlfZGF0YSwgDQogICAgaW5wdXRfbWV0YWRhdGEgPSBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwgbWluX2FidW5kYW5jZSA9IDAsDQogICAgbWluX3ByZXZhbGVuY2UgPSAwLG1pbl92YXJpYW5jZSA9IDAsDQogICAgb3V0cHV0ID0gZmlsZS5wYXRoKHBhdGhfbWFhc2xpbixncm91cDEpLCBtYXhfc2lnbmlmaWNhbmNlID0gMC4wNSwNCiAgICBmaXhlZF9lZmZlY3RzID0gYygnR3JvdXAnLCAnQ291bnRyeScpLGNvcnJlY3Rpb24gPSAiQkgiKQ0KDQpgYGANCg0KYGBge3J9DQp2b2xjYW5vMSA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShjb21wYXJpc29uX25hbWUpDQoNCnZvbGNhbm8yIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfaWxldW1fdW5pX3RheGEsdmFyaWFibGU9IkNvdW50cnkiKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vMSx2b2xjYW5vMiwgbmNvbD0yKQ0Kdm9sY2Fubw0KYGBgDQoNCiBHcm91cCAtIEludGVyc2VjdGlvbg0KDQpgYGB7cn0NCmludGVyc2VjdGlvbl9yZXN1bHRzIDwtIGdyb3VwX2ludGVyc2VjdGlvbihncm91cCwgbGlzdF9pbnRlcnNlY3Rpb25zLCBsaXN0X3Zlbm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQgPSBzZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzFdXQ0KbGlzdF92ZW5ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMl1dDQp2ZW5uIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1szXV0NCg0KIyBzaG93IHRoZSByZXN1bHRzDQp2ZW5uDQpgYGANCg0KIENvdW50cnkgLSBVbmlvbg0KDQpgYGB7cixldmFsPUZBTFNFfQ0KbGlzdF9jb3VudHJ5X3VuaW9uIDwtIGNvdW50cnlfdW5pb24oZ3JvdXAsbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCiBJbnRlcmFjdGlvbiBlZmZlY3QNCg0KYGBge3J9DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50IDwtIGNvdW50cnlfaW50ZXJhY3Rpb24oZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KIyBzZWUgdGhlIHJlc3VsdA0KIyMgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gZWZmZWN0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1sxXV0NCg0KIyMgcmVzdWx0cyBmb3IgY3plY2ggY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1syXV0NCg0KIyMgcmVzdWx0cyBmb3Igbm9yd2VnaWFuIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbM11dDQpgYGANCg0KUmVtb3ZpbmcgcHJvYmxlbWF0aWMgdGF4YQ0KDQpgYGB7cn0NCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSByZW1vdmluZ19pbnRlcmFjdGlvbl9wcm9ibGVtcyhncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIEJhc2ljIHN0YXRpc3RpY3MNCg0KYGBge3J9DQp1bmlfZGYgPC0gIG1lcmdlKGJhc2ljX3VuaXZhcmlhdGVfc3RhdGlzdGljcyhsaW5kYV9kYXRhLGdyb3VwKSwNCiAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JvdXAxXV0sDQogICAgICAgICAgICAgICAgIGJ5PSJTZXFJRCIsYWxsPVRSVUUpDQoNCnVuaV9kZltbImZpbmFsX3NpZyJdXSA8LSB1bmlfZGYkU2VxSUQgJWluJSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dW1siU2VxSUQiXV0NCnVuaV9zdGF0aXN0aWNzW1tzZWdtZW50XV1bW3Bhc3RlKGxldmVsLGNvbXBhcmlzb25fbmFtZSldXSA8LSB1bmlfZGYNCg0KIyBmb3IgY29tcGFyaXNvbg0KbmV3X25hbWUgPC0gcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKQ0KYWRkV29ya3NoZWV0KHN1cHBsZW1lbnRzX3diLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YShzdXBwbGVtZW50c193Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIyBub24tclBTQyB2cyBoZWFsdGh5DQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiaGVhbHRoeSIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQogbGluREENCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KbGluZGFfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJsaW5EQSIpDQoNCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gbGluZGFfZGF0YVtbMV1dDQpmaWx0X2lsZXVtX3VuaV90YXhhIDwtIGxpbmRhX2RhdGFbWzJdXQ0KZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEgPC0gbGluZGFfZGF0YVtbM11dDQoNCiMgZml0IHRoZSBtb2RlbA0KbGluZGEub2JqIDwtIGxpbmRhKGZpbHRfaWxldW1fdW5pX2RhdGEsIA0KICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLCANCiAgICAgICAgICAgICAgICAgICBmb3JtdWxhID0gJ34gR3JvdXAgKiBDb3VudHJ5JykNCg0KbGluZGEub3V0cHV0IDwtIGxpbmRhLm9iaiRvdXRwdXQNCmxpbmRhLm91dHB1dCA8LSBsaW5kYV9yZW5hbWluZyhsaW5kYS5vdXRwdXQsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCmdyb3VwMSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdKQ0KZ3JvdXAyIDwtIHBhc3RlMChncm91cFsxXSwgIiAsICIsZ3JvdXBbMl0sICIgLSBDWiB2cyBOTyIpIA0KZ3JvdXAzIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0sICI6Q291bnRyeU5PIikNCg0KZm9yIChncnAgaW4gYyhncm91cDEsZ3JvdXAyLGdyb3VwMykpew0KICByYXdfbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICByYXdsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfdGF4YSkNCiAgDQogIGxpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgbGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQp9DQoNCiMgc3VtbWFyeSBzdGF0aXN0aWNzDQojIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzIDwtIGJpbm9taWFsX3N0YXRpc3RpY3MoZmlsdF9pbGV1bV91bmlfZGF0YSwgICAgICAgICAgICAgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXA9Z3JvdXAsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXMsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9ICJ0ZXJtaW5hbF9pbGV1bSIpDQoNCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCiMgdm9sY2FubyBwbG90DQp2b2xjYW5vXzEgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShjb21wYXJpc29uX25hbWUpDQoNCnZvbGNhbm9fMiAgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfaWxldW1fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpIA0KDQp2b2xjYW5vXzMgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfaWxldW1fdW5pX3RheGEpICsNCiAgICAgICAgICAgIGdndGl0bGUoIkludGVyYWN0aW9uIikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2Fub18xLHZvbGNhbm9fMix2b2xjYW5vXzMsIG5jb2w9MykNCg0KYGBgDQoNCiBNYUFzTGluMg0KDQpgYGB7ciwgZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJyxtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQpmaXRfZGF0YSA9IE1hYXNsaW4yKA0KICAgIGlucHV0X2RhdGEgPSBmaWx0X2lsZXVtX3VuaV9kYXRhLCANCiAgICBpbnB1dF9tZXRhZGF0YSA9IGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLCBtaW5fYWJ1bmRhbmNlID0gMCwNCiAgICBtaW5fcHJldmFsZW5jZSA9IDAsbWluX3ZhcmlhbmNlID0gMCwNCiAgICBvdXRwdXQgPSBmaWxlLnBhdGgocGF0aF9tYWFzbGluLGdyb3VwMSksIG1heF9zaWduaWZpY2FuY2UgPSAwLjA1LA0KICAgIGZpeGVkX2VmZmVjdHMgPSBjKCdHcm91cCcsICdDb3VudHJ5JyksY29ycmVjdGlvbiA9ICJCSCIpDQoNCmBgYA0KDQpgYGB7cn0NCnZvbGNhbm8xIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfaWxldW1fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKGNvbXBhcmlzb25fbmFtZSkNCg0Kdm9sY2FubzIgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9pbGV1bV91bmlfdGF4YSx2YXJpYWJsZT0iQ291bnRyeSIpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQp2b2xjYW5vDQpgYGANCg0KIEdyb3VwIC0gSW50ZXJzZWN0aW9uDQoNCmBgYHtyfQ0KaW50ZXJzZWN0aW9uX3Jlc3VsdHMgPC0gZ3JvdXBfaW50ZXJzZWN0aW9uKGdyb3VwLCBsaXN0X2ludGVyc2VjdGlvbnMsIGxpc3RfdmVubnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMV1dDQpsaXN0X3Zlbm5zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1syXV0NCnZlbm4gPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzNdXQ0KDQojIHNob3cgdGhlIHJlc3VsdHMNCnZlbm4NCmBgYA0KDQogQ291bnRyeSAtIFVuaW9uDQoNCmBgYHtyLGV2YWw9RkFMU0V9DQpsaXN0X2NvdW50cnlfdW5pb24gPC0gY291bnRyeV91bmlvbihncm91cCxsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIEludGVyYWN0aW9uIGVmZmVjdA0KDQpgYGB7cn0NCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQgPC0gY291bnRyeV9pbnRlcmFjdGlvbihncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQojIHNlZSB0aGUgcmVzdWx0DQojIyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBlZmZlY3QNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzFdXQ0KDQojIyByZXN1bHRzIGZvciBjemVjaCBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzJdXQ0KDQojIyByZXN1bHRzIGZvciBub3J3ZWdpYW4gY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1szXV0NCmBgYA0KDQpSZW1vdmluZyBwcm9ibGVtYXRpYyB0YXhhDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIHJlbW92aW5nX2ludGVyYWN0aW9uX3Byb2JsZW1zKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQogQmFzaWMgc3RhdGlzdGljcw0KDQpgYGB7cn0NCnVuaV9kZiA8LSAgbWVyZ2UoYmFzaWNfdW5pdmFyaWF0ZV9zdGF0aXN0aWNzKGxpbmRhX2RhdGEsZ3JvdXApLA0KICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncm91cDFdXSwNCiAgICAgICAgICAgICAgICAgYnk9IlNlcUlEIixhbGw9VFJVRSkNCg0KdW5pX2RmW1siZmluYWxfc2lnIl1dIDwtIHVuaV9kZiRTZXFJRCAlaW4lIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCxjb21wYXJpc29uX25hbWUpXV1bWyJTZXFJRCJdXQ0KdW5pX3N0YXRpc3RpY3NbW3NlZ21lbnRdXVtbcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dIDwtIHVuaV9kZg0KDQojIGZvciBjb21wYXJpc29uDQpuZXdfbmFtZSA8LSBwYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpDQphZGRXb3Jrc2hlZXQoc3VwcGxlbWVudHNfd2IsIHNoZWV0TmFtZSA9IG5ld19uYW1lKQ0Kd3JpdGVEYXRhKHN1cHBsZW1lbnRzX3diLCBzaGVldCA9IG5ld19uYW1lLCB1bmlfZGYsIHJvd05hbWVzPUZBTFNFKQ0KYGBgDQoNCiMjIyMjIFZpc3VhbGl6YXRpb24NCg0KSGVhdG1hcCB2aXN1YWxpemluZyB0aGUgbGluREEncyBsb2dGb2xkQ2hhbmdlIGZvciB0YXhhIHdpdGggcCBcPCAwLjEuDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTcsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCmxpc3RfaGVhdG1hcCA8LSBsaXN0X2ludGVyc2VjdGlvbnNbZ3JlcChwYXN0ZShzZWdtZW50LGxldmVsKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lcyhsaXN0X2ludGVyc2VjdGlvbnMpLHZhbHVlPVRSVUUpXQ0KDQpwX2hlYXRtYXBfbGluZGEgPC0gaGVhdG1hcF9saW5kYShsaXN0X2hlYXRtYXAsaWxldW1fdGF4YV90YWIpDQpwX2hlYXRtYXBfbGluZGENCmBgYA0KDQpEb3QgaGVhdG1hcA0KDQpgYGB7ciwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9MTcsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCmRvdGhlYXRtYXBfbGluZGEgPC0gZG90X2hlYXRtYXBfbGluZGEobGlzdF9oZWF0bWFwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmlfc3RhdGlzdGljcyR0ZXJtaW5hbF9pbGV1bVtncmVwbChsZXZlbCxuYW1lcyh1bmlfc3RhdGlzdGljcyR0ZXJtaW5hbF9pbGV1bSkpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIpDQpkb3RoZWF0bWFwX2xpbmRhDQpgYGANCg0KIyMjIyMgclBTQyBlZmZlY3QNCg0KKipwcmVfTFR4IHZzIEhlYWx0aHkgYW5kIFBvc3RfTFR4IHZzIEhlYWx0aHkgaW50ZXJzZWN0aW9uKioNCg0KDQpgYGB7cn0NCkEgPC0gbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLCJoZWFsdGh5IHZzIHJQU0MiKV1dDQpCIDwtIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCwiaGVhbHRoeSB2cyBub24tclBTQyIpXV0NCmRmIDwtIEFbIShBJFNlcUlEICVpbiUgQiRTZXFJRCksXQ0KDQoNCnJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dIDwtIGRmDQogIA0KIyBzZWUgdGhlIHJlc3VsdHMNCnJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dIA0KYGBgDQoNCg0KIyMjIyBQaHlsdW0gbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0icGh5bHVtIg0KYGBgDQoNCmBgYHtyfQ0KcGF0aF9tYWFzbGluPSIuLi9pbnRlcm1lZGlhdGVfZmlsZXMvbWFhc2xpbi9RMi9QaHlsdW0vIg0KYGBgDQoNCmBgYHtyfQ0KcmF3X2xpbmRhX3Jlc3VsdHNfcGh5bHVtIDwtIGxpc3QoKTsNCnJhd19saW5kYV9yZXN1bHRzX3BoeWx1bVtbc2VnbWVudF1dIDwtIGxpc3QoKQ0KbGluZGFfcmVzdWx0c19waHlsdW0gPC0gbGlzdCgpOyANCmxpbmRhX3Jlc3VsdHNfcGh5bHVtW1tzZWdtZW50XV0gPC0gbGlzdCgpDQpgYGANCg0KQWdncmVnYXRlIHRheGENCg0KYGBge3J9DQpwaHlsdW1fZGF0YSA8LSBhZ2dyZWdhdGVfdGF4YShpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4b25vbWljX2xldmVsID0gIlBoeWx1bSIpDQoNCmlsZXVtX3BoeWx1bV90YWIgPC0gcGh5bHVtX2RhdGFbWzFdXQ0KaWxldW1fcGh5bHVtX3RheGFfdGFiIDwtIHBoeWx1bV9kYXRhW1syXV0NCg0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgbm9uLXJQU0MNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsInJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCioqbGluREEqKg0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpsaW5kYV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fcGh5bHVtX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9waHlsdW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJsaW5EQSIpDQoNCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gbGluZGFfZGF0YVtbMV1dDQpmaWx0X2lsZXVtX3VuaV90YXhhIDwtIGxpbmRhX2RhdGFbWzJdXQ0KZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEgPC0gbGluZGFfZGF0YVtbM11dDQoNCiMgZml0IHRoZSBtb2RlbA0KbGluZGEub2JqIDwtIGxpbmRhKGZpbHRfaWxldW1fdW5pX2RhdGEsIA0KICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLCANCiAgICAgICAgICAgICAgICAgICBmb3JtdWxhID0gJ34gR3JvdXAgKiBDb3VudHJ5JykNCg0KbGluZGEub3V0cHV0IDwtIGxpbmRhLm9iaiRvdXRwdXQNCmxpbmRhLm91dHB1dCA8LSBsaW5kYV9yZW5hbWluZyhsaW5kYS5vdXRwdXQsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCmdyb3VwMSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdKQ0KZ3JvdXAyIDwtIHBhc3RlMChncm91cFsxXSwgIiAsICIsZ3JvdXBbMl0sICIgLSBDWiB2cyBOTyIpIA0KZ3JvdXAzIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0sICI6Q291bnRyeU5PIikNCg0KZm9yIChncnAgaW4gYyhncm91cDEsZ3JvdXAyLGdyb3VwMykpew0KICByYXdfbGluZGFfcmVzdWx0c19waHlsdW1bW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgcmF3bGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQogIA0KICBsaW5kYV9yZXN1bHRzX3BoeWx1bVtbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICBsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfdGF4YSkNCn0NCg0KYGBgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KIyB2b2xjYW5vIHBsb3QNCnZvbGNhbm9fMSA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAxLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfaWxldW1fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKGNvbXBhcmlzb25fbmFtZSkNCg0Kdm9sY2Fub18yICA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoIkNvdW50cnkgZWZmZWN0IikgDQoNCnZvbGNhbm9fMyA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9pbGV1bV91bmlfdGF4YSkgKw0KICAgICAgICAgICAgZ2d0aXRsZSgiSW50ZXJhY3Rpb24iKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vXzEsdm9sY2Fub18yLHZvbGNhbm9fMywgbmNvbD0zKQ0KDQpgYGANCg0KIE1hQXNMaW4yDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmZpdF9kYXRhID0gTWFhc2xpbjIoDQogICAgaW5wdXRfZGF0YSA9IGZpbHRfaWxldW1fdW5pX2RhdGEsIA0KICAgIGlucHV0X21ldGFkYXRhID0gZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEsIG1pbl9hYnVuZGFuY2UgPSAwLA0KICAgIG1pbl9wcmV2YWxlbmNlID0gMCxtaW5fdmFyaWFuY2UgPSAwLA0KICAgIG91dHB1dCA9IGZpbGUucGF0aChwYXRoX21hYXNsaW4sZ3JvdXAxKSwgbWF4X3NpZ25pZmljYW5jZSA9IDAuMDUsDQogICAgZml4ZWRfZWZmZWN0cyA9IGMoJ0dyb3VwJywgJ0NvdW50cnknKSxjb3JyZWN0aW9uID0gIkJIIikNCg0KYGBgDQoNCmBgYHtyfQ0Kdm9sY2FubzEgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoY29tcGFyaXNvbl9uYW1lKQ0KDQp2b2xjYW5vMiA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2lsZXVtX3VuaV90YXhhLHZhcmlhYmxlPSJDb3VudHJ5IikgKyANCiAgICAgICAgICAgIGdndGl0bGUoIkNvdW50cnkgZWZmZWN0IikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2FubzEsdm9sY2FubzIsIG5jb2w9MikNCnZvbGNhbm8NCmBgYA0KDQpHcm91cCAtIEludGVyc2VjdGlvbg0KDQpgYGB7cn0NCmludGVyc2VjdGlvbl9yZXN1bHRzIDwtIGdyb3VwX2ludGVyc2VjdGlvbihncm91cCwgbGlzdF9pbnRlcnNlY3Rpb25zLCBsaXN0X3Zlbm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNfcGh5bHVtLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50ID0gc2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1sxXV0NCmxpc3RfdmVubnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzJdXQ0KdmVubiA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbM11dDQoNCiMgc2hvdyB0aGUgcmVzdWx0cw0KdmVubg0KYGBgDQoNCiBDb3VudHJ5IC0gVW5pb24NCg0KYGBge3IsZXZhbD1GQUxTRX0NCmxpc3RfY291bnRyeV91bmlvbiA8LSBjb3VudHJ5X3VuaW9uKGdyb3VwLGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQogSW50ZXJhY3Rpb24gZWZmZWN0DQoNCmBgYHtyfQ0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCA8LSBjb3VudHJ5X2ludGVyYWN0aW9uKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCiMgc2VlIHRoZSByZXN1bHQNCiMjIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGVmZmVjdA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMV1dDQoNCiMjIHJlc3VsdHMgZm9yIGN6ZWNoIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMl1dDQoNCiMjIHJlc3VsdHMgZm9yIG5vcndlZ2lhbiBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzNdXQ0KYGBgDQoNClJlbW92aW5nIHByb2JsZW1hdGljIHRheGENCg0KYGBge3J9DQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gcmVtb3ZpbmdfaW50ZXJhY3Rpb25fcHJvYmxlbXMoZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCiBCYXNpYyBzdGF0aXN0aWNzDQoNCmBgYHtyfQ0KdW5pX2RmIDwtICBtZXJnZShiYXNpY191bml2YXJpYXRlX3N0YXRpc3RpY3MobGluZGFfZGF0YSxncm91cCksDQogICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX3BoeWx1bVtbc2VnbWVudF1dW1tncm91cDFdXSwNCiAgICAgICAgICAgICAgICAgYnk9IlNlcUlEIixhbGw9VFJVRSkNCg0KdW5pX2RmW1siZmluYWxfc2lnIl1dIDwtIHVuaV9kZiRTZXFJRCAlaW4lIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCxjb21wYXJpc29uX25hbWUpXV1bWyJTZXFJRCJdXQ0KdW5pX3N0YXRpc3RpY3NbW3NlZ21lbnRdXVtbcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dIDwtIHVuaV9kZg0KDQojIGZvciBjb21wYXJpc29uDQpuZXdfbmFtZSA8LSBwYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpDQphZGRXb3Jrc2hlZXQoc3VwcGxlbWVudHNfd2IsIHNoZWV0TmFtZSA9IG5ld19uYW1lKQ0Kd3JpdGVEYXRhKHN1cHBsZW1lbnRzX3diLCBzaGVldCA9IG5ld19uYW1lLCB1bmlfZGYsIHJvd05hbWVzPUZBTFNFKQ0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgaGVhbHRoeQ0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQogbGluREENCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KbGluZGFfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX3BoeWx1bV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fcGh5bHVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9pbGV1bV91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfaWxldW1fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2lsZXVtX3VuaV9kYXRhLCANCiAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZm9ybXVsYSA9ICd+IEdyb3VwICogQ291bnRyeScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpncm91cDEgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSkNCmdyb3VwMiA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgLCAiLGdyb3VwWzJdLCAiIC0gQ1ogdnMgTk8iKSANCmdyb3VwMyA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdLCAiOkNvdW50cnlOTyIpDQoNCmZvciAoZ3JwIGluIGMoZ3JvdXAxLGdyb3VwMixncm91cDMpKXsNCiAgcmF3X2xpbmRhX3Jlc3VsdHNfcGh5bHVtW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIHJhd2xpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV90YXhhKQ0KICANCiAgbGluZGFfcmVzdWx0c19waHlsdW1bW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgbGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQp9DQoNCiMgc3VtbWFyeSBzdGF0aXN0aWNzDQojIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzIDwtIGJpbm9taWFsX3N0YXRpc3RpY3MoZmlsdF9pbGV1bV91bmlfZGF0YSwgICAgICAgICAgICAgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXA9Z3JvdXAsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXMsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9ICJ0ZXJtaW5hbF9pbGV1bSIpDQoNCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCiMgdm9sY2FubyBwbG90DQp2b2xjYW5vXzEgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShjb21wYXJpc29uX25hbWUpDQoNCnZvbGNhbm9fMiAgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfaWxldW1fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpIA0KDQp2b2xjYW5vXzMgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfaWxldW1fdW5pX3RheGEpICsNCiAgICAgICAgICAgIGdndGl0bGUoIkludGVyYWN0aW9uIikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2Fub18xLHZvbGNhbm9fMix2b2xjYW5vXzMsIG5jb2w9MykNCnZvbGNhbm8NCmBgYA0KDQogTWFBc0xpbjINCg0KYGBge3IsIGVjaG89RkFMU0UscmVzdWx0cz0naGlkZScsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KZml0X2RhdGEgPSBNYWFzbGluMigNCiAgICBpbnB1dF9kYXRhID0gZmlsdF9pbGV1bV91bmlfZGF0YSwgDQogICAgaW5wdXRfbWV0YWRhdGEgPSBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwgbWluX2FidW5kYW5jZSA9IDAsDQogICAgbWluX3ByZXZhbGVuY2UgPSAwLG1pbl92YXJpYW5jZSA9IDAsDQogICAgb3V0cHV0ID0gZmlsZS5wYXRoKHBhdGhfbWFhc2xpbixncm91cDEpLCBtYXhfc2lnbmlmaWNhbmNlID0gMC4wNSwNCiAgICBmaXhlZF9lZmZlY3RzID0gYygnR3JvdXAnLCAnQ291bnRyeScpLGNvcnJlY3Rpb24gPSAiQkgiKQ0KDQpgYGANCg0KYGBge3J9DQp2b2xjYW5vMSA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2lsZXVtX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShjb21wYXJpc29uX25hbWUpDQoNCnZvbGNhbm8yIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfaWxldW1fdW5pX3RheGEsdmFyaWFibGU9IkNvdW50cnkiKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vMSx2b2xjYW5vMiwgbmNvbD0yKQ0Kdm9sY2Fubw0KYGBgDQoNCiBHcm91cCAtIEludGVyc2VjdGlvbg0KDQpgYGB7cn0NCmludGVyc2VjdGlvbl9yZXN1bHRzIDwtIGdyb3VwX2ludGVyc2VjdGlvbihncm91cCwgbGlzdF9pbnRlcnNlY3Rpb25zLCBsaXN0X3Zlbm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNfcGh5bHVtLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50ID0gc2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1sxXV0NCmxpc3RfdmVubnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzJdXQ0KdmVubiA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbM11dDQoNCiMgc2hvdyB0aGUgcmVzdWx0cw0KdmVubg0KYGBgDQoNCiBDb3VudHJ5IC0gVW5pb24NCg0KYGBge3IsZXZhbD1GQUxTRX0NCmxpc3RfY291bnRyeV91bmlvbiA8LSBjb3VudHJ5X3VuaW9uKGdyb3VwLGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQogSW50ZXJhY3Rpb24gZWZmZWN0DQoNCmBgYHtyfQ0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCA8LSBjb3VudHJ5X2ludGVyYWN0aW9uKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCiMgc2VlIHRoZSByZXN1bHQNCiMjIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGVmZmVjdA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMV1dDQoNCiMjIHJlc3VsdHMgZm9yIGN6ZWNoIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMl1dDQoNCiMjIHJlc3VsdHMgZm9yIG5vcndlZ2lhbiBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzNdXQ0KYGBgDQoNClJlbW92aW5nIHByb2JsZW1hdGljIHRheGENCg0KYGBge3J9DQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gcmVtb3ZpbmdfaW50ZXJhY3Rpb25fcHJvYmxlbXMoZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCiBCYXNpYyBzdGF0aXN0aWNzDQoNCmBgYHtyfQ0KdW5pX2RmIDwtICBtZXJnZShiYXNpY191bml2YXJpYXRlX3N0YXRpc3RpY3MobGluZGFfZGF0YSxncm91cCksDQogICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX3BoeWx1bVtbc2VnbWVudF1dW1tncm91cDFdXSwNCiAgICAgICAgICAgICAgICAgYnk9IlNlcUlEIixhbGw9VFJVRSkNCg0KdW5pX2RmW1siZmluYWxfc2lnIl1dIDwtIHVuaV9kZiRTZXFJRCAlaW4lIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCxjb21wYXJpc29uX25hbWUpXV1bWyJTZXFJRCJdXQ0KdW5pX3N0YXRpc3RpY3NbW3NlZ21lbnRdXVtbcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dIDwtIHVuaV9kZg0KDQojIGZvciBjb21wYXJpc29uDQpuZXdfbmFtZSA8LSBwYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpDQphZGRXb3Jrc2hlZXQoc3VwcGxlbWVudHNfd2IsIHNoZWV0TmFtZSA9IG5ld19uYW1lKQ0Kd3JpdGVEYXRhKHN1cHBsZW1lbnRzX3diLCBzaGVldCA9IG5ld19uYW1lLCB1bmlfZGYsIHJvd05hbWVzPUZBTFNFKQ0KYGBgDQoNCiMjIyMjIG5vbi1yUFNDIHZzIGhlYWx0aHkNCg0KYGBge3J9DQpncm91cCA8LSBjKCJoZWFsdGh5Iiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCiBsaW5EQQ0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpsaW5kYV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fcGh5bHVtX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9waHlsdW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJsaW5EQSIpDQoNCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gbGluZGFfZGF0YVtbMV1dDQpmaWx0X2lsZXVtX3VuaV90YXhhIDwtIGxpbmRhX2RhdGFbWzJdXQ0KZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEgPC0gbGluZGFfZGF0YVtbM11dDQoNCiMgZml0IHRoZSBtb2RlbA0KbGluZGEub2JqIDwtIGxpbmRhKGZpbHRfaWxldW1fdW5pX2RhdGEsIA0KICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX21ldGFkYXRhLCANCiAgICAgICAgICAgICAgICAgICBmb3JtdWxhID0gJ34gR3JvdXAgKiBDb3VudHJ5JykNCg0KbGluZGEub3V0cHV0IDwtIGxpbmRhLm9iaiRvdXRwdXQNCmxpbmRhLm91dHB1dCA8LSBsaW5kYV9yZW5hbWluZyhsaW5kYS5vdXRwdXQsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCmdyb3VwMSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdKQ0KZ3JvdXAyIDwtIHBhc3RlMChncm91cFsxXSwgIiAsICIsZ3JvdXBbMl0sICIgLSBDWiB2cyBOTyIpIA0KZ3JvdXAzIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0sICI6Q291bnRyeU5PIikNCg0KZm9yIChncnAgaW4gYyhncm91cDEsZ3JvdXAyLGdyb3VwMykpew0KICByYXdfbGluZGFfcmVzdWx0c19waHlsdW1bW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgcmF3bGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX3RheGEpDQogIA0KICBsaW5kYV9yZXN1bHRzX3BoeWx1bVtbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICBsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgZmlsdF9pbGV1bV91bmlfdGF4YSkNCn0NCg0KIyBzdW1tYXJ5IHN0YXRpc3RpY3MNCiMgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXMgPC0gYmlub21pYWxfc3RhdGlzdGljcyhmaWx0X2lsZXVtX3VuaV9kYXRhLCAgICAgICAgICAgICANCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cD1ncm91cCwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0c19nZW51cywNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50ID0gInRlcm1pbmFsX2lsZXVtIikNCg0KYGBgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KIyB2b2xjYW5vIHBsb3QNCnZvbGNhbm9fMSA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAxLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfaWxldW1fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKGNvbXBhcmlzb25fbmFtZSkNCg0Kdm9sY2Fub18yICA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoIkNvdW50cnkgZWZmZWN0IikgDQoNCnZvbGNhbm9fMyA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9pbGV1bV91bmlfdGF4YSkgKw0KICAgICAgICAgICAgZ2d0aXRsZSgiSW50ZXJhY3Rpb24iKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vXzEsdm9sY2Fub18yLHZvbGNhbm9fMywgbmNvbD0zKQ0KDQpgYGANCg0KIE1hQXNMaW4yDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmZpdF9kYXRhID0gTWFhc2xpbjIoDQogICAgaW5wdXRfZGF0YSA9IGZpbHRfaWxldW1fdW5pX2RhdGEsIA0KICAgIGlucHV0X21ldGFkYXRhID0gZmlsdF9pbGV1bV91bmlfbWV0YWRhdGEsIG1pbl9hYnVuZGFuY2UgPSAwLA0KICAgIG1pbl9wcmV2YWxlbmNlID0gMCxtaW5fdmFyaWFuY2UgPSAwLA0KICAgIG91dHB1dCA9IGZpbGUucGF0aChwYXRoX21hYXNsaW4sZ3JvdXAxKSwgbWF4X3NpZ25pZmljYW5jZSA9IDAuMDUsDQogICAgZml4ZWRfZWZmZWN0cyA9IGMoJ0dyb3VwJywgJ0NvdW50cnknKSxjb3JyZWN0aW9uID0gIkJIIikNCg0KYGBgDQoNCmBgYHtyfQ0Kdm9sY2FubzEgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9pbGV1bV91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUoY29tcGFyaXNvbl9uYW1lKQ0KDQp2b2xjYW5vMiA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2lsZXVtX3VuaV90YXhhLHZhcmlhYmxlPSJDb3VudHJ5IikgKyANCiAgICAgICAgICAgIGdndGl0bGUoIkNvdW50cnkgZWZmZWN0IikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2FubzEsdm9sY2FubzIsIG5jb2w9MikNCnZvbGNhbm8NCmBgYA0KDQogR3JvdXAgLSBJbnRlcnNlY3Rpb24NCg0KYGBge3J9DQppbnRlcnNlY3Rpb25fcmVzdWx0cyA8LSBncm91cF9pbnRlcnNlY3Rpb24oZ3JvdXAsIGxpc3RfaW50ZXJzZWN0aW9ucywgbGlzdF92ZW5ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX3BoeWx1bSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMV1dDQpsaXN0X3Zlbm5zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1syXV0NCnZlbm4gPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzNdXQ0KDQojIHNob3cgdGhlIHJlc3VsdHMNCnZlbm4NCmBgYA0KDQogQ291bnRyeSAtIFVuaW9uDQoNCmBgYHtyLGV2YWw9RkFMU0V9DQpsaXN0X2NvdW50cnlfdW5pb24gPC0gY291bnRyeV91bmlvbihncm91cCxsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIEludGVyYWN0aW9uIGVmZmVjdA0KDQpgYGB7cn0NCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQgPC0gY291bnRyeV9pbnRlcmFjdGlvbihncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2lsZXVtX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQojIHNlZSB0aGUgcmVzdWx0DQojIyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBlZmZlY3QNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzFdXQ0KDQojIyByZXN1bHRzIGZvciBjemVjaCBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzJdXQ0KDQojIyByZXN1bHRzIGZvciBub3J3ZWdpYW4gY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1szXV0NCmBgYA0KDQpSZW1vdmluZyBwcm9ibGVtYXRpYyB0YXhhDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIHJlbW92aW5nX2ludGVyYWN0aW9uX3Byb2JsZW1zKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQogQmFzaWMgc3RhdGlzdGljcw0KDQpgYGB7cn0NCnVuaV9kZiA8LSAgbWVyZ2UoYmFzaWNfdW5pdmFyaWF0ZV9zdGF0aXN0aWNzKGxpbmRhX2RhdGEsZ3JvdXApLA0KICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0c19waHlsdW1bW3NlZ21lbnRdXVtbZ3JvdXAxXV0sDQogICAgICAgICAgICAgICAgIGJ5PSJTZXFJRCIsYWxsPVRSVUUpDQoNCnVuaV9kZltbImZpbmFsX3NpZyJdXSA8LSB1bmlfZGYkU2VxSUQgJWluJSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dW1siU2VxSUQiXV0NCnVuaV9zdGF0aXN0aWNzW1tzZWdtZW50XV1bW3Bhc3RlKGxldmVsLGNvbXBhcmlzb25fbmFtZSldXSA8LSB1bmlfZGYNCg0KIyBmb3IgY29tcGFyaXNvbg0KbmV3X25hbWUgPC0gcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKQ0KYWRkV29ya3NoZWV0KHN1cHBsZW1lbnRzX3diLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YShzdXBwbGVtZW50c193Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIyBWaXN1YWxpemF0aW9uDQoNCkhlYXRtYXAgdmlzdWFsaXppbmcgdGhlIGxpbkRBJ3MgbG9nRm9sZENoYW5nZSBmb3IgdGF4YSB3aXRoIHAgXDwgMC4xLg0KDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTE3LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpsaXN0X2hlYXRtYXAgPC0gbGlzdF9pbnRlcnNlY3Rpb25zW2dyZXAocGFzdGUoc2VnbWVudCxsZXZlbCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXMobGlzdF9pbnRlcnNlY3Rpb25zKSx2YWx1ZT1UUlVFKV0NCg0KcF9oZWF0bWFwX2xpbmRhIDwtIGhlYXRtYXBfbGluZGEobGlzdF9oZWF0bWFwLGlsZXVtX3RheGFfdGFiKQ0KcF9oZWF0bWFwX2xpbmRhDQpgYGANCg0KRG90IGhlYXRtYXANCg0KYGBge3IsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTE3LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpkb3RoZWF0bWFwX2xpbmRhIDwtIGRvdF9oZWF0bWFwX2xpbmRhKGxpc3RfaGVhdG1hcCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pX3N0YXRpc3RpY3MkdGVybWluYWxfaWxldW1bZ3JlcGwobGV2ZWwsbmFtZXModW5pX3N0YXRpc3RpY3MkdGVybWluYWxfaWxldW0pKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiKQ0KZG90aGVhdG1hcF9saW5kYQ0KYGBgDQoNCiMjIyMjIHJQU0MgZWZmZWN0DQoNCioqcHJlX0xUeCB2cyBIZWFsdGh5IGFuZCBQb3N0X0xUeCB2cyBIZWFsdGh5IGludGVyc2VjdGlvbioqDQoNCg0KYGBge3J9DQpBIDwtIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCwiaGVhbHRoeSB2cyByUFNDIildXQ0KQiA8LSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsImhlYWx0aHkgdnMgbm9uLXJQU0MiKV1dDQpkZiA8LSBBWyEoQSRTZXFJRCAlaW4lIEIkU2VxSUQpLF0NCg0KcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0gPC0gZGYNCiAgDQojIHNlZSB0aGUgcmVzdWx0cw0KcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0gDQpgYGANCg0KIyMjIyBTYXZpbmcgcmVzdWx0cw0KDQpgYGB7cn0NCiMgQUxMIERBVEENCnNhdmVXb3JrYm9vayhzdXBwbGVtZW50c193YixmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInN1cHBsZW1lbnRzX3VuaV9hbmFseXNpc193Yl8iLHNlZ21lbnQsIi54bHN4IikpLG92ZXJ3cml0ZSA9IFRSVUUpDQoNCiMgUFNDIGVmZmVjdA0Kd3JpdGUueGxzeChycHNjX2VmZmVjdCwNCiAgICAgICAgICBmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInN1cHBsZW1lbnRzX3Jwc2NfZWZmZWN0XyIsc2VnbWVudCwiLnhsc3giKSkpDQoNCiMgU0lHTklGSUNBTlQgdGF4YQ0Kd3JpdGUueGxzeChsaXN0X2ludGVyc2VjdGlvbnNbZ3JlcGwoc2VnbWVudCxuYW1lcyhsaXN0X2ludGVyc2VjdGlvbnMpKV0gJT4lDQogICAgICAgICAgICBgbmFtZXM8LWAoZ3N1YihzZWdtZW50LCAiIiwgbmFtZXMoDQogICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9uc1tncmVwbChzZWdtZW50LG5hbWVzKGxpc3RfaW50ZXJzZWN0aW9ucykpXSkpKSwNCiAgICAgICAgICAgZmlsZS5wYXRoKHBhdGgscGFzdGUwKCJzdXBwbGVtZW50c19zaWduaWZpY2FudF90YXhhXyIsc2VnbWVudCwiLnhsc3giKSkpDQpgYGANCg0KDQojIyBNYWNoaW5lIGxlYXJuaW5nDQoNCmBgYHtyfQ0KcGF0aCA9ICIuLi9yZXN1bHRzL1EyL21vZGVscyINCmBgYA0KDQojIyMgRWxhc3RpY05ldA0KDQpgYGB7cn0NCm1vZGVsPSJlbmV0Ig0KYGBgDQoNCiMjIyMgQVNWIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9IkFTViINCmBgYA0KDQojIyMjIyByUFNDIHZzIG5vbi1yUFNDDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQptb2RlbHNfc3VtbSA8LSBsaXN0KCkNCm1vZGVsc19jbSA8LSBsaXN0KCkNCmJldGFzIDwtIGxpc3QoKQ0Kcm9jX2NzIDwtIGxpc3QoKQ0KDQptb2RlbHNfc3VtbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KbW9kZWxzX2NtW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzJG9yaWdpbmFsDQpyb2NfY3NbW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCmJldGFzW1ttb2RlbF9uYW1lXV0gPC0gYXMubWF0cml4KGVuZXRfbW9kZWwkYmV0YXMpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0KZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzDQplbmV0X21vZGVsJHBsb3QNCnJvY19jDQpgYGANCg0KIyMjIyMgclBTQyB2cyBoZWFsdGh5DQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQw0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCm1vZGVsc19zdW1tW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQptb2RlbHNfY21bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGNvbmZfbWF0cmljZXMkb3JpZ2luYWwNCnJvY19jc1tbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KYmV0YXNbW21vZGVsX25hbWVdXSA8LSBhcy5tYXRyaXgoZW5ldF9tb2RlbCRiZXRhcykNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQplbmV0X21vZGVsJGNvbmZfbWF0cmljZXMNCmVuZXRfbW9kZWwkcGxvdA0KDQpyb2NfYw0KYGBgDQoNCiMjIyMjIG5vbi1yUFNDIHZzIGhlYWx0aHkNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQw0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCm1vZGVsc19zdW1tW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQptb2RlbHNfY21bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGNvbmZfbWF0cmljZXMkb3JpZ2luYWwNCnJvY19jc1tbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KYmV0YXNbW21vZGVsX25hbWVdXSA8LSBhcy5tYXRyaXgoZW5ldF9tb2RlbCRiZXRhcykNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQplbmV0X21vZGVsJGNvbmZfbWF0cmljZXMNCmVuZXRfbW9kZWwkcGxvdA0KDQpyb2NfYw0KYGBgDQoNCiMjIyMjIHJQU0MgZWZmZWN0DQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQplbmV0X21vZGVsIDwtIGdsbW5ldF9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DDQpyb2NfYyA8LSByb2NfY3VydmUoZW5ldF9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KbW9kZWxzX3N1bW1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCm1vZGVsc19jbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkY29uZl9tYXRyaWNlcyRvcmlnaW5hbA0Kcm9jX2NzW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQpiZXRhc1tbbW9kZWxfbmFtZV1dIDwtIGFzLm1hdHJpeChlbmV0X21vZGVsJGJldGFzKQ0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCmVuZXRfbW9kZWwkY29uZl9tYXRyaWNlcw0KZW5ldF9tb2RlbCRwbG90DQoNCnJvY19jDQpgYGANCg0KIyMjIyBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpBZ2dyZWdhdGUgdGF4YQ0KDQpgYGB7cn0NCmdlbnVzX2RhdGEgPC0gYWdncmVnYXRlX3RheGEoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheG9ub21pY19sZXZlbCA9IGxldmVsKQ0KDQppbGV1bV9nZW51c190YWIgPC0gZ2VudXNfZGF0YVtbMV1dDQppbGV1bV9nZW51c190YXhhX3RhYiA8LSBnZW51c19kYXRhW1syXV0NCmBgYA0KDQojIyMjIyByUFNDIHZzIG5vbi1yUFNDDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQw0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCm1vZGVsc19zdW1tW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQptb2RlbHNfY21bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGNvbmZfbWF0cmljZXMkb3JpZ2luYWwNCnJvY19jc1tbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KYmV0YXNbW21vZGVsX25hbWVdXSA8LSBhcy5tYXRyaXgoZW5ldF9tb2RlbCRiZXRhcykNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQplbmV0X21vZGVsJGNvbmZfbWF0cmljZXMNCmVuZXRfbW9kZWwkcGxvdA0KDQpyb2NfYw0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgaGVhbHRoeQ0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQptb2RlbHNfc3VtbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KbW9kZWxzX2NtW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzJG9yaWdpbmFsDQpyb2NfY3NbW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCmJldGFzW1ttb2RlbF9uYW1lXV0gPC0gYXMubWF0cml4KGVuZXRfbW9kZWwkYmV0YXMpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0KZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzDQplbmV0X21vZGVsJHBsb3QNCg0Kcm9jX2MNCmBgYA0KDQojIyMjIyBub24tclBTQyB2cyBoZWFsdGh5DQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSxncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQw0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCm1vZGVsc19zdW1tW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQptb2RlbHNfY21bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGNvbmZfbWF0cmljZXMkb3JpZ2luYWwNCnJvY19jc1tbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KYmV0YXNbW21vZGVsX25hbWVdXSA8LSBhcy5tYXRyaXgoZW5ldF9tb2RlbCRiZXRhcykNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQplbmV0X21vZGVsJGNvbmZfbWF0cmljZXMNCmVuZXRfbW9kZWwkcGxvdA0Kcm9jX2MNCmBgYA0KDQojIyMjIyByUFNDIGVmZmVjdA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQplbmV0X21vZGVsIDwtIGdsbW5ldF9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DDQpyb2NfYyA8LSByb2NfY3VydmUoZW5ldF9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KbW9kZWxzX3N1bW1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCm1vZGVsc19jbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkY29uZl9tYXRyaWNlcyRvcmlnaW5hbA0Kcm9jX2NzW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQpiZXRhc1tbbW9kZWxfbmFtZV1dIDwtIGFzLm1hdHJpeChlbmV0X21vZGVsJGJldGFzKQ0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCmVuZXRfbW9kZWwkY29uZl9tYXRyaWNlcw0KZW5ldF9tb2RlbCRwbG90DQoNCnJvY19jDQpgYGANCg0KIyMjIyBTYXZpbmcgcmVzdWx0cw0KDQpgYGB7cn0NCm1vZGVsc19zdW1tX2RmX2lsZXVtIDwtIGRvLmNhbGwocmJpbmQsIA0KICBtb2RlbHNfc3VtbVtncmVwKHNlZ21lbnQsbmFtZXMobW9kZWxzX3N1bW0pLHZhbHVlID0gVFJVRSldKQ0KDQp3cml0ZS5jc3YobW9kZWxzX3N1bW1fZGZfaWxldW0sZmlsZS5wYXRoKHBhdGgscGFzdGUwKCJlbGFzdGljX25ldF8iLHNlZ21lbnQsIi5jc3YiKSkpDQpgYGANCg0KDQojIyMgU3VwcGxlbWVudGFyeSBtb2RlbHMNCg0KYGBge3J9DQpzdXBwbGVtZW50c19tb2RlbHMgPC0gbGlzdCgpDQpgYGANCg0KIyMjIyBDTFItdHJhbnNmb3JtZWQgZGF0YQ0KDQojIyMjIyBrTk4NCg0KYGBge3J9DQptb2RlbD0ia25uIg0KYGBgDQoNCiMjIyMjIyBBU1YgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iQVNWIg0KYGBgDQoNCioqKnJQU0MgdnMgbm9uLXJQU0MqKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoa25uX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoa25uX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQprbm5fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyBlZmZlY3QqKg0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoa25uX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQprbm5fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCiMjIyMjIyBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpBZ2dyZWdhdGUgdGF4YQ0KDQpgYGB7cn0NCmdlbnVzX2RhdGEgPC0gYWdncmVnYXRlX3RheGEoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheG9ub21pY19sZXZlbCA9IGxldmVsKQ0KDQppbGV1bV9nZW51c190YWIgPC0gZ2VudXNfZGF0YVtbMV1dDQppbGV1bV9nZW51c190YXhhX3RhYiA8LSBnZW51c19kYXRhW1syXV0NCmBgYA0KDQoqKnJQU0MgdnMgbm9uLXJQU0MqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyBSYW5kb20gRm9yZXN0DQoNCmBgYHtyfQ0KbW9kZWw9InJmIg0KYGBgDQoNCiMjIyMjIyBBU1YgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iQVNWIg0KYGBgDQoNCioqKnJQU0MgdnMgbm9uLXJQU0MqKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpyZl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyBlZmZlY3QqKg0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpyZl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KIyMjIyMjIEdlbnVzIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9ImdlbnVzIg0KYGBgDQoNCkFnZ3JlZ2F0ZSB0YXhhDQoNCmBgYHtyfQ0KZ2VudXNfZGF0YSA8LSBhZ2dyZWdhdGVfdGF4YShpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4b25vbWljX2xldmVsID0gbGV2ZWwpDQoNCmlsZXVtX2dlbnVzX3RhYiA8LSBnZW51c19kYXRhW1sxXV0NCmlsZXVtX2dlbnVzX3RheGFfdGFiIDwtIGdlbnVzX2RhdGFbWzJdXQ0KYGBgDQoNCioqclBTQyB2cyBub24tclBTQyoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpyZl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpyZl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpyZl9tb2RlbCA8LSByZl9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUocmZfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpyZl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KIyMjIyMgR3JhZGllbnQgYm9vc3RpbmcNCg0KYGBge3J9DQptb2RlbD0iZ2IiDQpgYGANCg0KIyMjIyMjIEFTViBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJBU1YiDQpgYGANCg0KKioqclBTQyB2cyBub24tclBTQyoqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyBlZmZlY3QqKg0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCiMjIyMjIyBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpBZ2dyZWdhdGUgdGF4YQ0KDQpgYGB7cn0NCmdlbnVzX2RhdGEgPC0gYWdncmVnYXRlX3RheGEoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheG9ub21pY19sZXZlbCA9IGxldmVsKQ0KDQppbGV1bV9nZW51c190YWIgPC0gZ2VudXNfZGF0YVtbMV1dDQppbGV1bV9nZW51c190YXhhX3RhYiA8LSBnZW51c19kYXRhW1syXV0NCmBgYA0KDQoqKnJQU0MgdnMgbm9uLXJQU0MqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIFJlbGF0aXZlIGFidW5kYW5jZXMNCg0KIyMjIyMgRWxhc3RpYyBuZXQNCg0KIyMjIyMjIEFTViBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJBU1YiDQpgYGANCg0KKioqclBTQyB2cyBub24tclBTQyoqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImVuZXRfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyMgR2VudXMgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iZ2VudXMiDQpgYGANCg0KQWdncmVnYXRlIHRheGENCg0KYGBge3J9DQpnZW51c19kYXRhIDwtIGFnZ3JlZ2F0ZV90YXhhKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhvbm9taWNfbGV2ZWwgPSBsZXZlbCkNCg0KaWxldW1fZ2VudXNfdGFiIDwtIGdlbnVzX2RhdGFbWzFdXQ0KaWxldW1fZ2VudXNfdGF4YV90YWIgPC0gZ2VudXNfZGF0YVtbMl1dDQpgYGANCg0KKipyUFNDIHZzIG5vbi1yUFNDKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImVuZXRfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImVuZXRfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImVuZXRfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyBrTk4NCg0KIyMjIyMjIEFTViBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJBU1YiDQpgYGANCg0KKioqclBTQyB2cyBub24tclBTQyoqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sia25uX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sia25uX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyMgR2VudXMgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iZ2VudXMiDQpgYGANCg0KQWdncmVnYXRlIHRheGENCg0KYGBge3J9DQpnZW51c19kYXRhIDwtIGFnZ3JlZ2F0ZV90YXhhKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhvbm9taWNfbGV2ZWwgPSBsZXZlbCkNCg0KaWxldW1fZ2VudXNfdGFiIDwtIGdlbnVzX2RhdGFbWzFdXQ0KaWxldW1fZ2VudXNfdGF4YV90YWIgPC0gZ2VudXNfZGF0YVtbMl1dDQpgYGANCg0KKipyUFNDIHZzIG5vbi1yUFNDKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoa25uX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImtubl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQprbm5fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyBlZmZlY3QqKg0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyBSYW5kb20gRm9yZXN0DQoNCiMjIyMjIyBBU1YgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iQVNWIg0KYGBgDQoNCioqKnJQU0MgdnMgbm9uLXJQU0MqKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpyZl9tb2RlbCA8LSByZl9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUocmZfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCiMjIyMjIyBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpBZ2dyZWdhdGUgdGF4YQ0KDQpgYGB7cn0NCmdlbnVzX2RhdGEgPC0gYWdncmVnYXRlX3RheGEoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheG9ub21pY19sZXZlbCA9IGxldmVsKQ0KDQppbGV1bV9nZW51c190YWIgPC0gZ2VudXNfZGF0YVtbMV1dDQppbGV1bV9nZW51c190YXhhX3RhYiA8LSBnZW51c19kYXRhW1syXV0NCmBgYA0KDQoqKnJQU0MgdnMgbm9uLXJQU0MqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpyZl9tb2RlbCA8LSByZl9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUocmZfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpyZl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fZ2VudXNfdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCiMjIyMjIEdyYWRpZW50IGJvb3N0aW5nDQoNCiMjIyMjIyBBU1YgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iQVNWIg0KYGBgDQoNCioqKnJQU0MgdnMgbm9uLXJQU0MqKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2lsZXVtX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyBlZmZlY3QqKg0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfaWxldW1fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGlsZXVtX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KIyMjIyMjIEdlbnVzIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9ImdlbnVzIg0KYGBgDQoNCkFnZ3JlZ2F0ZSB0YXhhDQoNCmBgYHtyfQ0KZ2VudXNfZGF0YSA8LSBhZ2dyZWdhdGVfdGF4YShpbGV1bV9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4b25vbWljX2xldmVsID0gbGV2ZWwpDQoNCmlsZXVtX2dlbnVzX3RhYiA8LSBnZW51c19kYXRhW1sxXV0NCmlsZXVtX2dlbnVzX3RheGFfdGFiIDwtIGdlbnVzX2RhdGFbWzJdXQ0KYGBgDQoNCioqclBTQyB2cyBub24tclBTQyoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9pbGV1bV91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGlsZXVtX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoaWxldW1fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9pbGV1bV91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2lsZXVtX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChpbGV1bV9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c190YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfaWxldW1fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KIyMjIyBTYXZpbmcgcmVzdWx0cw0KDQpgYGB7cn0NCm1vZGVsc19saXN0IDwtIGxpc3QoKQ0KDQpmb3IgKG1vZGVsX25hbWUgaW4gbmFtZXMoc3VwcGxlbWVudHNfbW9kZWxzJG1vZGVsc19zdW1tKSl7DQogIGRmIDwtIGRvLmNhbGwocmJpbmQsIHN1cHBsZW1lbnRzX21vZGVscyRtb2RlbHNfc3VtbVtbbW9kZWxfbmFtZV1dKQ0KICBtb2RlbHNfbGlzdFtbbW9kZWxfbmFtZV1dIDwtIGRmDQp9DQoNCndyaXRlLnhsc3gobW9kZWxzX2xpc3QsDQogICAgICAgICAgIGZpbGU9ZmlsZS5wYXRoKHBhdGgscGFzdGUwKCJzdXBwbGVtZW50c19tb2RlbHNfIixzZWdtZW50LCIueGxzeCIpKSwNCiAgICAgICAgICAgcm93TmFtZXM9VFJVRSkNCg0KYGBgDQoNCg0KIyMgUmVzdWx0cyBvdmVydmlldw0KDQojIyMjIEFscGhhIGRpdmVyc2l0eQ0KDQpgYGB7cn0NCnBjX29ic2VydmVkW1tzZWdtZW50XV0NCnBjX3NoYW5ub25bW3NlZ21lbnRdXQ0KcGNfc2ltcHNvbltbc2VnbWVudF1dDQpwY19waWVsb3VbW3NlZ21lbnRdXQ0KYGBgDQoNClBsb3RzDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KYWxwaGFfZGl2X3Bsb3RzW1twYXN0ZShzZWdtZW50LCJDb3VudHJ5IildXQ0KYGBgDQoNCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD00LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQphbHBoYV9kaXZfcGxvdHNbW3Bhc3RlKHNlZ21lbnQsIkN1c3RvbSIpXV0NCmBgYA0KDQojIyMjIEJldGEgZGl2ZXJzaXR5DQoNCioqTWFpbiByZXN1bHRzKioNCg0KYGBge3J9DQpwYWlyd2lzZV9haXRjaGlzb25fcmF3W1twYXN0ZSgiZ2VudXMiLCBzZWdtZW50KV1dDQpgYGANCg0KUENBDQoNCmBgYHtyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD0zLCBmaWcuZnVsbHdpZHRoPVRSVUUsIGV2YWw9VFJVRX0NCnBjYV9wbG90c19saXN0W1twYXN0ZShzZWdtZW50LCJnZW51cyBjdXN0b20iKV1dDQpgYGANCg0KKipTdXBwbGVtZW50cyoqDQoNCmBgYHtyfQ0Ka25pdHI6OmthYmxlKHN1cHBsZW1lbnRzX2JldGFbIWdyZXBsKCJQQ29BIixuYW1lcyhzdXBwbGVtZW50c19iZXRhKSldLA0KICAgICAgICAgICAgIGRpZ2l0cyA9IDMsDQogICAgICAgICAgICAgY2FwdGlvbiA9ICJTdXBwbGVtZW50YXJ5IFBFUk1BTk9WQSByZXN1bHRzIikNCmBgYA0KDQpQQ0ENCg0KYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTcsIGZpZy5mdWxsd2lkdGg9VFJVRSwgZXZhbD1GQUxTRX0NCmdnYXJyYW5nZShwbG90bGlzdCA9IHN1cHBsZW1lbnRzX2JldGFbZ3JlcGwoIlBDb0EiLG5hbWVzKHN1cHBsZW1lbnRzX2JldGEpKV0sDQogICAgICAgICAgbGFiZWxzPW5hbWVzKHN1cHBsZW1lbnRzX2JldGFbZ3JlcGwoIlBDb0EiLG5hbWVzKHN1cHBsZW1lbnRzX2JldGEpKV0pLA0KICAgICAgICAgIGZvbnQubGFiZWwgPSBsaXN0KHNpemU9NSxmYWNlPSJwbGFpbiIpLA0KICAgICAgICAgIG5jb2w9Mixucm93PTMpDQpgYGANCg0KIyMjIyBVbml2YXJpYXRlIGFuYWx5c2lzDQoNCioqTnVtYmVyIG9mIHNpZ25pZmljYW50IHRheGEqKg0KDQpgYGB7cn0NCmtuaXRyOjprYWJsZShjYmluZChhcy5kYXRhLmZyYW1lKGxhcHBseShsaXN0X2ludGVyc2VjdGlvbnMsbnJvdykpLA0KICAgICAgYXMuZGF0YS5mcmFtZShsYXBwbHkocnBzY19lZmZlY3QsbnJvdykpKSAlPiUgdCgpICU+JSANCiAgYGNvbG5hbWVzPC1gKCJDb3VudCIpICU+JSANCiAgYHJvd25hbWVzPC1gKGMobmFtZXMobGlzdF9pbnRlcnNlY3Rpb25zKSwiUFNDIGVmZmVjdCBBU1YiLCJQU0MgZWZmZWN0IEdlbnVzIikpLGNhcHRpb249Ik51bWJlciBvZiBzaWduaWZpY2FudCB0YXhhIikNCmBgYA0KDQoqKkNvdW50cyoqDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KIyB1bml2YXJfbGlzdCA8LSB1bml2YXJpYXRlX3N0YXRpc3RpY3MobGlzdF9pbnRlcnNlY3Rpb25zLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHNjX2VmZmVjdCwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlsZXVtX2dlbnVzX2Fzdl90YXhhX3RhYikNCiMgDQojIHVuaXZhcl9kZiA8LSB1bml2YXJfbGlzdFtbMV1dDQojIHdiIDwtIHVuaXZhcl9saXN0W1syXV0NCiMgDQojICMgc2F2ZSB0aGUgcmVzdWx0cw0KIyBzYXZlV29ya2Jvb2sod2IsInJlc3VsdHMvUTEvREFBX2ZpbmFsX3Rlcm1pbmFsX2lsZXVtLnhsc3giLCBvdmVyd3JpdGUgPSBUUlVFKQ0KIyANCiMgIyBzZWUgdGhlIHJlc3VsdHMNCiMgdW5pdmFyX2RmDQpgYGANCg0KIyMjIyBNYWNoaW5lIGxlYXJuaW5nDQoNCioqTWFpbiBtb2RlbHMqKg0KDQpTdW1tYXJ5DQoNCmBgYHtyfQ0Ka25pdHI6OmthYmxlKG1vZGVsc19zdW1tX2RmX2lsZXVtICU+JSBkcGx5cjo6c2VsZWN0KA0KImFscGhhIiwibGFtYmRhIiwNCiJhdWNfb3B0aW1pc21fY29ycmVjdGVkIiwNCiJhdWNfb3B0aW1pc21fY29ycmVjdGVkX0NJTCIsDQoiYXVjX29wdGltaXNtX2NvcnJlY3RlZF9DSVUiKSwNCiAgICAgICAgICAgICBkaWdpdHM9MixjYXB0aW9uPSJFbGFzdGljIG5ldCByZXN1bHRzIikNCmBgYA0KDQoqKlJPQyAtIEFTViBsZXZlbCoqDQoNCmBgYHtyfQ0Kcm9jX2N1cnZlX2FsbF9jdXN0b20ocm9jX2NzW2MoMTo0KV0sIA0KICAgICAgICAgICAgICAgICAgICAgUT0iUTIiLA0KICAgICAgICAgICAgICAgICAgICAgbW9kZWxfbmFtZT0iZW5ldF9tb2RlbCIpDQpgYGANCg0KKipST0MgLSBHZW51cyBsZXZlbCoqDQoNCmBgYHtyfQ0Kcm9jX2N1cnZlX2FsbF9jdXN0b20ocm9jX2NzW2MoNTo4KV0sUT0iUTIiLA0KICAgICAgICAgICAgICAgICAgICAgbW9kZWxfbmFtZT0iZW5ldF9tb2RlbCIpDQpgYGANCg0KKipTdXBwbGVtZW50YXJ5IG1vZGVscyoqDQoNClN1bW1hcnkNCg0KYGBge3J9DQojIEJ1aWxkIGZpbmFsIGRhdGFmcmFtZQ0KbW9kZWxzX2xpc3RbWyJlbmV0X21vZGVsIl1dIDwtIG1vZGVsc19zdW1tX2RmX2lsZXVtDQpmaW5hbF9kZiA8LSB0aWJibGUocm93X25hbWVzID0gcm93bmFtZXMobW9kZWxzX2xpc3RbWzFdXSkpDQoNCiMgTG9vcCB0aHJvdWdoIG1vZGVscyBhbmQgZXh0cmFjdCByZXF1aXJlZCB2YWx1ZXMNCmZvciAobW9kZWxfbmFtZSBpbiBuYW1lcyhtb2RlbHNfbGlzdCkpIHsNCiAgbW9kZWxfZGYgPC0gbW9kZWxzX2xpc3RbW21vZGVsX25hbWVdXQ0KICANCiAgIyBDb21iaW5lIEFVQ19vcHRpbWlzbV9jb3JyZWN0ZWQgd2l0aCBpdHMgQ0kgdmFsdWVzDQogIGZpbmFsX2RmW1ttb2RlbF9uYW1lXV0gPC0gcGFzdGUwKA0KICAgIHJvdW5kKG1vZGVsX2RmJGF1Y19vcHRpbWlzbV9jb3JyZWN0ZWQsIDMpLCANCiAgICAiICgiLCByb3VuZChtb2RlbF9kZiRhdWNfb3B0aW1pc21fY29ycmVjdGVkX0NJTCwgMyksICI7ICIsIA0KICAgIHJvdW5kKG1vZGVsX2RmJGF1Y19vcHRpbWlzbV9jb3JyZWN0ZWRfQ0lVLCAzKSwgIikiDQogICkNCn0NCg0Ka25pdHI6OmthYmxlKGZpbmFsX2RmLCBjYXB0aW9uPSJBbGwgbW9kZWxzIikNCmBgYA0KDQpST0MgLSBBU1YNCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD04LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpyb2NzX2xpc3QgPC0gc3VwcGxlbWVudHNfbW9kZWxzJHJvY19jcw0Kcm9jc19saXN0W1siZW5ldF9tb2RlbCJdXSA8LSByb2NfY3MNCg0KcGxvdF9saXN0IDwtIGxpc3QoKQ0KDQpmb3IgKG1vZGVsX25hbWUgaW4gbmFtZXMocm9jc19saXN0KSkgew0KICBwbG90X2xpc3RbW21vZGVsX25hbWVdXSA8LSByb2NfY3VydmVfYWxsX2N1c3RvbShyb2NzX2xpc3RbW21vZGVsX25hbWVdXVtjKDE6NCldLA0KICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIsDQogICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX25hbWU9bW9kZWxfbmFtZSkNCn0NCg0KZ2dhcnJhbmdlKHBsb3RsaXN0ID0gcGxvdF9saXN0LGxhYmVscyA9IG5hbWVzKHJvY3NfbGlzdCksZm9udC5sYWJlbCA9IGxpc3QoZmFjZT0icGxhaW4iLHNpemU9NykpDQpgYGANCg0KUk9DIC0gZ2VudXMNCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD04LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpwbG90X2xpc3QgPC0gbGlzdCgpDQoNCmZvciAobW9kZWxfbmFtZSBpbiBuYW1lcyhyb2NzX2xpc3QpKSB7DQogIHBsb3RfbGlzdFtbbW9kZWxfbmFtZV1dIDwtIHJvY19jdXJ2ZV9hbGxfY3VzdG9tKHJvY3NfbGlzdFtbbW9kZWxfbmFtZV1dW2MoNTo4KV0sDQogICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfbmFtZT1tb2RlbF9uYW1lKQ0KfQ0KDQpwIDwtIGdnYXJyYW5nZShwbG90bGlzdCA9IHBsb3RfbGlzdCxsYWJlbHMgPSBuYW1lcyhyb2NzX2xpc3QpLGZvbnQubGFiZWwgPSBsaXN0KGZhY2U9InBsYWluIixzaXplPTcpKQ0KcA0KYGBgDQoNCmBgYHtyLHJlc3VsdHM9J2hpZGUnfQ0KcGRmKCIuLi9maWd1cmVzL1EyL21vZGVsc19pbGV1bS5wZGYiLA0KICAgIGhlaWdodCA9MTAsd2lkdGggPSAxMCkNCnANCmRldi5vZmYoKQ0KYGBgDQoNCiMgQW5hbHlzaXMgLSBDb2xvbg0KDQpgYGB7cn0NCnNlZ21lbnQ9ImNvbG9uIg0KYGBgDQoNCiMjIEZpbHRlcmluZw0KDQpSdWxlczogLSBwcmV2YWxlbmNlIFw+IDUlIChwZXIgZ3JvdXApIC0gbmVhclplcm9WYXIgd2l0aCBkZWZhdWx0DQpzZXR0aW5ncyAtIHNlcXVlbmNpbmcgZGVwdGggXD4gNTAwMCAtIHRheG9ub21pYyBhc3NpZ25tZW50IGF0IGxlYXN0DQpvcmRlcg0KDQoqKlJhcmVmYWN0aW9uIEN1cnZlKioNCg0KYGBge3J9DQpwYXRoPSIuLi9pbnRlcm1lZGlhdGVfZmlsZXMvcmFyZWN1cnZlcyINCnNlcV9kZXB0aF90aHJlc2hvbGQgPC0gMTAwMDANCmBgYA0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFfQ0KcHMgPC0gY29uc3RydWN0X3BoeWxvc2VxKGNvbG9uX2Fzdl90YWIsY29sb25fdGF4YV90YWIsY29sb25fbWV0YWRhdGEpDQpyYXJlcmVzIDwtIGdldF9yYXJlY3VydmUob2JqPXBzLCBjaHVua3M9NTAwKQ0Kc2F2ZShyYXJlcmVzLGZpbGUgPSBmaWxlLnBhdGgocGF0aCwicmFyZWZhY3Rpb25fY29sb24uUmRhdGEiKSkNCmBgYA0KDQpgYGB7cn0NCmxvYWQoZmlsZS5wYXRoKHBhdGgsInJhcmVmYWN0aW9uX2NvbG9uLlJkYXRhIikpDQpzZXFfZGVwdGhfdGhyZXNob2xkIDwtIDEwMDAwDQpwcmFyZSA8LSBnZ3JhcmVjdXJ2ZShvYmo9cmFyZXJlcywNCiAgICAgICAgICAgICAgICAgICAgICBmYWN0b3JOYW1lcz0iQ291bnRyeSIsDQogICAgICAgICAgICAgICAgICAgICAgaW5kZXhOYW1lcz1jKCJPYnNlcnZlIikpICsgDQogICAgICAgIHRoZW1lX2J3KCkrDQogICAgICAgIHRoZW1lKGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSwgDQogICAgICAgICAgICAgIHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91cj1OQSxmaWxsPSJncmV5IiksDQogICAgICAgICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChmYWNlPSJib2xkIikpICsgDQogICAgICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHNlcV9kZXB0aF90aHJlc2hvbGQsIA0KICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSArIA0KICAgICAgICB4bGltKDAsIDIwMDAwKQ0KDQpwcmFyZQ0KYGBgDQoNCkxpYnJhcnkgc2l6ZQ0KDQpgYGB7ciwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KcmVhZF9jb3VudHMoY29sb25fYXN2X3RhYiwgbGluZSA9IGMoNTAwMCwxMDAwMCkpDQpgYGANCg0KIyMjIFNlcXVlbmNpbmcgZGVwdGgNCg0KYGBge3J9DQpkYXRhX2ZpbHQgPC0gc2VxX2RlcHRoX2ZpbHRlcmluZyhjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcV9kZXB0aF90aHJlc2hvbGQgPSAxMDAwMCkNCg0KZmlsdF9jb2xvbl9hc3ZfdGFiIDwtIGRhdGFfZmlsdFtbMV1dOyBhbHBoYV9jb2xvbl9hc3ZfdGFiIDwtIGZpbHRfY29sb25fYXN2X3RhYg0KZmlsdF9jb2xvbl90YXhhX3RhYiA8LSBkYXRhX2ZpbHRbWzJdXTsgYWxwaGFfY29sb25fdGF4YV90YWIgPC0gZmlsdF9jb2xvbl90YXhhX3RhYg0KZmlsdF9jb2xvbl9tZXRhZGF0YSA8LSBkYXRhX2ZpbHRbWzNdXTsgYWxwaGFfY29sb25fbWV0YWRhdGEgPC0gZmlsdF9jb2xvbl9tZXRhZGF0YQ0KDQpzZXFfc3RlcCA8LSBkaW0oZmlsdF9jb2xvbl9hc3ZfdGFiKVsxXQ0KYGBgDQoNCkxpYnJhcnkgc2l6ZQ0KDQpgYGB7ciwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KcmVhZF9jb3VudHMoZmlsdF9jb2xvbl9hc3ZfdGFiLGxpbmUgPSBjKDEwMDAwKSkNCmBgYA0KDQojIyMgTmVhclplcm9WYXINCg0KYGBge3J9DQpkYXRhX2ZpbHQgPC0gbmVhcnplcm92YXJfZmlsdGVyaW5nKGZpbHRfY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9tZXRhZGF0YSkNCg0KZmlsdF9jb2xvbl9hc3ZfdGFiIDwtIGRhdGFfZmlsdFtbMV1dDQpmaWx0X2NvbG9uX3RheGFfdGFiIDwtIGRhdGFfZmlsdFtbMl1dDQpuZWFyemVyb19zdGVwIDwtIGRpbShmaWx0X2NvbG9uX2Fzdl90YWIpWzFdDQpgYGANCg0KTGlicmFyeSBzaXplDQoNCmBgYHtyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD00LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpyZWFkX2NvdW50cyhmaWx0X2NvbG9uX2Fzdl90YWIsbGluZSA9IGMoNTAwMCwxMDAwMCkpDQpgYGANCg0KQ2hlY2sgemVybyBkZXB0aA0KDQpgYGB7cn0NCmRhdGFfZmlsdCA8LSBjaGVja196ZXJvX2RlcHRoKGZpbHRfY29sb25fYXN2X3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3RheGFfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fbWV0YWRhdGEpDQoNCmZpbHRfY29sb25fYXN2X3RhYiA8LSBkYXRhX2ZpbHRbWzFdXTsgDQpmaWx0X2NvbG9uX3RheGFfdGFiIDwtIGRhdGFfZmlsdFtbMl1dOyANCmZpbHRfY29sb25fbWV0YWRhdGEgPC0gZGF0YV9maWx0W1szXV07IA0KYGBgDQoNCkxpYnJhcnkgc2l6ZQ0KDQpgYGB7ciwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KcmVhZF9jb3VudHMoZmlsdF9jb2xvbl9hc3ZfdGFiLGxpbmUgPSBjKDUwMDAsMTAwMDApKQ0KYGBgDQoNCiMjIyBGaW5hbCBDb3VudHMNCg0KYGBge3J9DQpmaW5hbF9jb3VudHNfZmlsdGVyaW5nKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgc2VxX3N0ZXAsIDAsIG5lYXJ6ZXJvX3N0ZXApDQpgYGANCg0KIyMgQWxwaGEgZGl2ZXJzaXR5DQoNCmBgYHtyfQ0KcGF0aCA9ICIuLi9yZXN1bHRzL1EyL2FscGhhX2RpdmVyc2l0eSINCmBgYA0KDQoqKkNhbGN1bGF0aW9uKioNCg0KYGBge3J9DQojIENvbnN0cnVjdCBNUFNFIG9iamVjdA0KYWxwaGFfY29sb25fbWV0YWRhdGEkU2FtcGxlIDwtIGFscGhhX2NvbG9uX21ldGFkYXRhJFNhbXBsZUlEDQpjb2xvbl9tcHNlIDwtIGFzLk1QU0UoY29uc3RydWN0X3BoeWxvc2VxKGFscGhhX2NvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhX2NvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYV9jb2xvbl9tZXRhZGF0YSkpDQoNCmNvbG9uX21wc2UgJTw+JSBtcF9ycmFyZWZ5KHJhcmVzaXplID0gMTAwMDAsc2VlZCA9IDEyMykNCg0KIyBDYWxjdWxhdGUgYWxwaGEgZGl2ZXJzaXR5IC0gcmFyZWZpZWQgY291bnRzDQpjb2xvbl9tcHNlICU8PiUgbXBfY2FsX2FscGhhKC5hYnVuZGFuY2U9UmFyZUFidW5kYW5jZSwgZm9yY2U9VFJVRSkNCmBgYA0KDQpgYGB7cn0NCmFscGhhX2RhdGEgPC0gZGF0YS5mcmFtZShTYW1wbGVJRD1jb2xvbl9tcHNlJFNhbXBsZS54LA0KICAgICAgICAgICAgICAgICAgICAgICAgIE9ic2VydmU9Y29sb25fbXBzZSRPYnNlcnZlLA0KICAgICAgICAgICAgICAgICAgICAgICAgIFNoYW5ub249Y29sb25fbXBzZSRTaGFubm9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgIFNpbXBzb249Y29sb25fbXBzZSRTaW1wc29uLA0KICAgICAgICAgICAgICAgICAgICAgICAgIFBpZWxvdT1jb2xvbl9tcHNlJFBpZWxvdSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBHcm91cD1jb2xvbl9tcHNlJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgIENvdW50cnk9Y29sb25fbXBzZSRDb3VudHJ5LA0KICAgICAgICAgICAgICAgICAgICAgICAgIFBhdGllbnQ9Y29sb25fbXBzZSRQYXRpZW50KQ0KDQp3cml0ZS5jc3YoYWxwaGFfZGF0YSxmaWxlLnBhdGgocGF0aCxwYXN0ZTAoImFscGhhX2luZGljZXNfIixzZWdtZW50LCIuY3N2IikpLA0KICAgICAgICAgIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCioqUGxvdHMqKg0KDQojIyMgQ291bnRyeSBwbG90DQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KcF9ib3hwbG90X2FscGhhIDwtIGFscGhhX2RpdmVyc2l0eV9jb3VudHJpZXMoYWxwaGFfZGF0YSkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQphbHBoYV9kaXZfcGxvdHNbW3Bhc3RlKHNlZ21lbnQsIkNvdW50cnkiKV1dIDwtIHBfYm94cGxvdF9hbHBoYQ0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcF9ib3hwbG90X2FscGhhDQpgYGANCg0KYGBge3IscmVzdWx0cz0naGlkZSd9DQpwZGYoIi4uL2ZpZ3VyZXMvUTIvYWxwaGFfZGl2ZXJzaXR5X2NvbG9uLnBkZiIsDQogICAgaGVpZ2h0ID00LHdpZHRoID0gNykNCnBfYm94cGxvdF9hbHBoYQ0KZGV2Lm9mZigpDQpgYGANCg0KIyMjIEN1c3RvbSBwbG90DQoNCmBgYHtyfQ0KYWxwaGFfZGF0YSA8LSBhbHBoYV9kYXRhICU+JSANCiAgZHBseXI6OnNlbGVjdCgtYygiU2ltcHNvbiIsIlBpZWxvdSIpKSAlPiUNCiAgbXV0YXRlKFJpY2huZXNzPU9ic2VydmUpDQoNCnBfQiA8LSBhbHBoYV9kaXZlcnNpdHlfY3VzdG9tXzIoYWxwaGFfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjMpDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KYWxwaGFfZGl2X3Bsb3RzW1twYXN0ZShzZWdtZW50LCJDdXN0b20iKV1dIDwtIHBfQg0KDQpwX0INCmBgYA0KDQojIyMgTGluZWFyIE1vZGVsDQoNCmBgYHtyfQ0KcGF0aCA9ICIuLi9yZXN1bHRzL1EyL2FscGhhX2RpdmVyc2l0eSINCmFscGhhX2RhdGEgPC0gcmVhZC5jc3YoZmlsZS5wYXRoKHBhdGgscGFzdGUwKCJhbHBoYV9pbmRpY2VzXyIsc2VnbWVudCwiLmNzdiIpKSkNCmBgYA0KDQoqKlJpY2huZXNzKioNCg0KYGBge3J9DQpyZXN1bHRzX21vZGVsIDwtIHBhaXJ3aXNlLmxtZXIoDQogIGZvcm11bGEgPSAiT2JzZXJ2ZSB+IEdyb3VwICogQ291bnRyeSArICgxfFBhdGllbnQpIiwNCiAgZmFjdG9ycz1hbHBoYV9kYXRhJEdyb3VwLA0KICBkYXRhPWFscGhhX2RhdGEpDQoNCiMgY2hlY2sgaW50ZXJhY3Rpb24NCmlmICghaXMuZGF0YS5mcmFtZShyZXN1bHRzX21vZGVsKSl7DQogIHJlc3VsdHNfbW9kZWxfb2JzZXJ2ZSA8LSByZXN1bHRzX21vZGVsW1sxXV0NCiAgcmVzdWx0c19tb2RlbF9vYnNlcnZlX2RldGFpbGVkIDwtIHJlc3VsdHNfbW9kZWxbWzJdXQ0KfSBlbHNlIHsNCiAgcmVzdWx0c19tb2RlbF9vYnNlcnZlIDwtIHJlc3VsdHNfbW9kZWwNCiAgcmVzdWx0c19tb2RlbF9vYnNlcnZlX2RldGFpbGVkIDwtIE5BDQp9DQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KcGNfb2JzZXJ2ZWRbW3NlZ21lbnRdXSA8LSByZXN1bHRzX21vZGVsX29ic2VydmUNCmBgYA0KDQpgYGB7cn0NCiMgc2VlIHRoZSByZXN1bHRzDQprbml0cjo6a2FibGUocmVzdWx0c19tb2RlbF9vYnNlcnZlLGRpZ2l0cyA9IDMsDQpjYXB0aW9uID0gIlJhdyByZXN1bHRzIG9mIGxpbmVhciBtb2RlbCBvZiByaWNobmVzcyBlc3RpbWF0aW9uLiIpDQoNCmtuaXRyOjprYWJsZShyZXN1bHRzX21vZGVsX29ic2VydmVfZGV0YWlsZWQsZGlnaXRzID0gMywNCmNhcHRpb24gPSAiUmF3IHJlc3VsdHMgb2YgaW5kZXBlbmRlbnQgY291bnRyeSBhbmFseXNpcyIpDQpgYGANCg0KKipTaGFubm9uKioNCg0KYGBge3J9DQpyZXN1bHRzX21vZGVsIDwtIHBhaXJ3aXNlLmxtZXIoDQogIGZvcm11bGEgPSAiU2hhbm5vbiB+IEdyb3VwICogQ291bnRyeSArICgxfFBhdGllbnQpIiwNCiAgZmFjdG9ycz1hbHBoYV9kYXRhJEdyb3VwLA0KICBkYXRhPWFscGhhX2RhdGEpDQoNCiMgY2hlY2sgaW50ZXJhY3Rpb24NCmlmICghaXMuZGF0YS5mcmFtZShyZXN1bHRzX21vZGVsKSl7DQogIHJlc3VsdHNfbW9kZWxfc2hhbm5vbiA8LSByZXN1bHRzX21vZGVsW1sxXV0NCiAgcmVzdWx0c19tb2RlbF9zaGFubm9uX2RldGFpbGVkIDwtIHJlc3VsdHNfbW9kZWxbWzJdXQ0KfSBlbHNlIHsNCiAgcmVzdWx0c19tb2RlbF9zaGFubm9uIDwtIHJlc3VsdHNfbW9kZWwNCiAgcmVzdWx0c19tb2RlbF9zaGFubm9uX2RldGFpbGVkIDwtIE5BDQp9DQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KcGNfc2hhbm5vbltbc2VnbWVudF1dIDwtIGFzLmRhdGEuZnJhbWUocmVzdWx0c19tb2RlbF9zaGFubm9uKQ0KDQpgYGANCg0KYGBge3J9DQojIHNlZSB0aGUgcmVzdWx0cw0Ka25pdHI6OmthYmxlKHJlc3VsdHNfbW9kZWxfc2hhbm5vbixkaWdpdHMgPSAzLA0KY2FwdGlvbiA9ICJSYXcgcmVzdWx0cyBvZiBsaW5lYXIgbW9kZWwgb2YgU2hhbm5vbiBlc3RpbWF0aW9uLiIpDQoNCmtuaXRyOjprYWJsZShyZXN1bHRzX21vZGVsX3NoYW5ub25fZGV0YWlsZWQsZGlnaXRzID0gMywNCmNhcHRpb24gPSAiUmF3IHJlc3VsdHMgb2YgaW5kZXBlbmRlbnQgY291bnRyeSBhbmFseXNpcyIpDQpgYGANCg0KKipTaW1wc29uKioNCg0KYGBge3J9DQpyZXN1bHRzX21vZGVsIDwtIHBhaXJ3aXNlLmxtZXIoDQogIGZvcm11bGEgPSAiU2ltcHNvbiB+IEdyb3VwICogQ291bnRyeSArICgxfFBhdGllbnQpIiwNCiAgZmFjdG9ycz1hbHBoYV9kYXRhJEdyb3VwLA0KICBkYXRhPWFscGhhX2RhdGEpDQoNCiMgY2hlY2sgaW50ZXJhY3Rpb24NCmlmICghaXMuZGF0YS5mcmFtZShyZXN1bHRzX21vZGVsKSl7DQogIHJlc3VsdHNfbW9kZWxfc2ltcHNvbiA8LSByZXN1bHRzX21vZGVsW1sxXV0NCiAgcmVzdWx0c19tb2RlbF9zaW1wc29uX2RldGFpbGVkIDwtIHJlc3VsdHNfbW9kZWxbWzJdXQ0KfSBlbHNlIHsNCiAgcmVzdWx0c19tb2RlbF9zaW1wc29uIDwtIHJlc3VsdHNfbW9kZWwNCiAgcmVzdWx0c19tb2RlbF9zaW1wc29uX2RldGFpbGVkIDwtIE5BDQp9DQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KcGNfc2ltcHNvbltbc2VnbWVudF1dIDwtIGFzLmRhdGEuZnJhbWUocmVzdWx0c19tb2RlbF9zaW1wc29uKQ0KDQpgYGANCg0KYGBge3J9DQojIHNlZSB0aGUgcmVzdWx0cw0Ka25pdHI6OmthYmxlKHJlc3VsdHNfbW9kZWxfc2ltcHNvbixkaWdpdHMgPSAzLA0KY2FwdGlvbiA9ICJSYXcgcmVzdWx0cyBvZiBsaW5lYXIgbW9kZWwgb2YgU2ltcHNvbiBlc3RpbWF0aW9uLiIpDQoNCmtuaXRyOjprYWJsZShyZXN1bHRzX21vZGVsX3NpbXBzb25fZGV0YWlsZWQsZGlnaXRzID0gMywNCmNhcHRpb24gPSAiUmF3IHJlc3VsdHMgb2YgaW5kZXBlbmRlbnQgY291bnRyeSBhbmFseXNpcyIpDQpgYGANCg0KKipQaWVsb3UqKg0KDQpgYGB7cn0NCnJlc3VsdHNfbW9kZWwgPC0gcGFpcndpc2UubG1lcigNCiAgZm9ybXVsYSA9ICJQaWVsb3UgfiBHcm91cCAqIENvdW50cnkgKyAoMXxQYXRpZW50KSIsDQogIGZhY3RvcnM9YWxwaGFfZGF0YSRHcm91cCwNCiAgZGF0YT1hbHBoYV9kYXRhKQ0KDQojIGNoZWNrIGludGVyYWN0aW9uDQppZiAoIWlzLmRhdGEuZnJhbWUocmVzdWx0c19tb2RlbCkpew0KICByZXN1bHRzX21vZGVsX3BpZWxvdSA8LSByZXN1bHRzX21vZGVsW1sxXV0NCiAgcmVzdWx0c19tb2RlbF9waWVsb3VfZGV0YWlsZWQgPC0gcmVzdWx0c19tb2RlbFtbMl1dDQp9IGVsc2Ugew0KICByZXN1bHRzX21vZGVsX3BpZWxvdSA8LSByZXN1bHRzX21vZGVsDQogIHJlc3VsdHNfbW9kZWxfcGllbG91X2RldGFpbGVkIDwtIE5BDQp9DQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KcGNfcGllbG91W1tzZWdtZW50XV0gPC0gYXMuZGF0YS5mcmFtZShyZXN1bHRzX21vZGVsX3BpZWxvdSkNCg0KYGBgDQoNCmBgYHtyfQ0KIyBzZWUgdGhlIHJlc3VsdHMNCmtuaXRyOjprYWJsZShyZXN1bHRzX21vZGVsX3BpZWxvdSxkaWdpdHMgPSAzLA0KY2FwdGlvbiA9ICJSYXcgcmVzdWx0cyBvZiBsaW5lYXIgbW9kZWwgb2YgUGllbG91IGVzdGltYXRpb24uIikNCg0Ka25pdHI6OmthYmxlKHJlc3VsdHNfbW9kZWxfcGllbG91X2RldGFpbGVkLGRpZ2l0cyA9IDMsDQpjYXB0aW9uID0gIlJhdyByZXN1bHRzIG9mIGluZGVwZW5kZW50IGNvdW50cnkgYW5hbHlzaXMiKQ0KYGBgDQoNCiMjIyBTYXZpbmcgcmVzdWx0cw0KDQpgYGB7cn0NCmFscGhhX2xpc3QgPC0gbGlzdCgNCiAgUmljaG5lc3M9cGNfb2JzZXJ2ZWRbW3NlZ21lbnRdXSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJDb21wYXJpc29uIiksDQogIFNoYW5ub249cGNfc2hhbm5vbltbc2VnbWVudF1dICU+JSByb3duYW1lc190b19jb2x1bW4oIkNvbXBhcmlzb24iKSwNCiAgU2ltcHNvbj1wY19zaW1wc29uW1tzZWdtZW50XV0gJT4lIHJvd25hbWVzX3RvX2NvbHVtbigiQ29tcGFyaXNvbiIpLA0KICBQaWVsb3U9cGNfcGllbG91W1tzZWdtZW50XV0gJT4lIHJvd25hbWVzX3RvX2NvbHVtbigiQ29tcGFyaXNvbiIpKQ0KICAgICAgICAgICAgICAgICAgIA0Kd3JpdGUueGxzeChhbHBoYV9saXN0LCANCiAgICAgICAgICAgZmlsZSA9IGZpbGUucGF0aChwYXRoLHBhc3RlMCgiYWxwaGFfZGl2ZXJzaXR5X3Jlc3VsdHNfIixzZWdtZW50LCIueGxzeCIpKSkNCmBgYA0KDQojIyBCZXRhIGRpdmVyc2l0eQ0KDQpDYWxjdWxhdGluZyBBaXRjaGlzb24gZGlzdGFuY2UgKGV1Y2xpZGVhbiBkaXN0YW5jZSBvbiBjbHItdHJhbnNmb3JtZWQNCmRhdGEpLCBib3RoIGF0IEFTViBhbmQgZ2VudXMgbGV2ZWwuDQoNCiMjIyBNYWluIGFuYWx5c2lzIC0gR2VudXMsIEFpdGNoaXNvbg0KDQoqKkdlbnVzIGxldmVsLCBBaXRjaGlzb24gZGlzdGFuY2UqKg0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpgYGB7cn0NCnBhdGggPSAiLi4vcmVzdWx0cy9RMi9iZXRhX2RpdmVyc2l0eSINCmBgYA0KDQpBZ2dyZWdhdGlvbiwgZmlsdGVyaW5nDQoNCmBgYHtyfQ0KZ2VudXNfZGF0YSA8LSBhZ2dyZWdhdGVfdGF4YShjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4b25vbWljX2xldmVsPWxldmVsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lcz1UUlVFKQ0KDQpmaWx0X2RhdGEgPC0gZmlsdGVyaW5nX3N0ZXBzKGdlbnVzX2RhdGFbWzFdXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VudXNfZGF0YVtbMl1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXFfZGVwdGhfdGhyZXNob2xkPTEwMDAwKQ0KDQpmaWx0X2NvbG9uX2dlbnVzX3RhYiA8LSBmaWx0X2RhdGFbWzFdXQ0KZmlsdF9jb2xvbl9nZW51c190YXhhIDwtIGZpbHRfZGF0YVtbMl1dDQpmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhIDwtIGZpbHRfZGF0YVtbM11dDQpgYGANCg0KIyMjIyMgUEVSTUFOT1ZBDQoNCmBgYHtyfQ0KcGFpcndpc2VfZGYgPC0gZmlsdF9jb2xvbl9nZW51c190YWIgJT4lIGNvbHVtbl90b19yb3duYW1lcygiU2VxSUQiKSAlPiUgdCgpDQoNCiMgbWFpbiBlZmZlY3QNCnBwX21haW4gPC0gcGFpcndpc2UuYWRvbmlzKHBhaXJ3aXNlX2RmLGZpbHRfY29sb25fZ2VudXNfbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGUgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJENvdW50cnksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudHMgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJFBhdGllbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaW0ubWV0aG9kID0gInJvYnVzdC5haXRjaGlzb24iLCBwLmFkanVzdC5tPSJCSCIpDQoNCiMgaW50ZXJhY3Rpb24NCnBwX2ludCA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSRDb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24gPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudHMgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJFBhdGllbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHNpbS5tZXRob2QgPSAicm9idXN0LmFpdGNoaXNvbiIsIHAuYWRqdXN0Lm09IkJIIikNCg0KIyB0aWR5IHRoZSByZXN1bHRzDQpwcF9mYWN0b3IgPC0gcHBfbWFpbltbMV1dDQpwcF9jb3YgPC0gcHBfbWFpbltbMl1dDQpwcF9mYWMuY292IDwtIHBwX2ludFtbM11dDQoNCmNvbHMgPC0gYygicGFpcnMiLCJEZiIsIlN1bXNPZlNxcyIsICJGLk1vZGVsIiwiUjIiLCJwLnZhbHVlIiwgInAuYWRqdXN0ZWQiLCAic2lnIikNCmNvbG5hbWVzKHBwX2ZhY3RvcikgPC0gY29sczsgY29sbmFtZXMocHBfY292KSA8LSBjb2xzOyBjb2xuYW1lcyhwcF9mYWMuY292KSA8LSBjb2xzOyANCg0KIyBzYXZlIHJhdyByZXN1bHRzDQpwYWlyd2lzZV9haXRjaGlzb25fcmF3W1twYXN0ZShsZXZlbCwgc2VnbWVudCldXSA8LXJiaW5kKHBwX2ZhY3RvcixwcF9jb3YscHBfZmFjLmNvdikNCg0KYGBgDQoNCmBgYHtyfQ0KIyBzZWUgdGhlIHJlc3VsdHMNCmtuaXRyOjprYWJsZShwcF9mYWN0b3IsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgR1JPVVAgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIENPVU5UUlkgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfZmFjLmNvdixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBJTlRFUkFDVElPTiBHUk9VUDpDb3VudHJ5IikNCmBgYA0KDQpJbnRlcmFjdGlvbiBjaGVjaw0KDQpgYGB7cn0NCmludGVyYWN0aW9uX3NpZyA8LSBwcF9mYWMuY292JHBhaXJzW3BwX2ZhYy5jb3YkcC5hZGp1c3RlZCA8IDAuMDVdDQoNCmlmIChsZW5ndGgoaW50ZXJhY3Rpb25fc2lnKT4wKXsNCiBmb3IgKGkgaW4gMTpsZW5ndGgoaW50ZXJhY3Rpb25fc2lnKSl7DQogIGdyb3VwMSA8LSB1bmxpc3Qoc3Ryc3BsaXQoaW50ZXJhY3Rpb25fc2lnW2ldLHNwbGl0ID0gIiB2cyAiKSlbMV0NCiAgZ3JvdXAyIDwtIHVubGlzdChzdHJzcGxpdChpbnRlcmFjdGlvbl9zaWdbaV0sc3BsaXQgPSAiIHZzICIpKVsyXQ0KICBncm91cDIgPC0gdW5saXN0KHN0cnNwbGl0KGdyb3VwMixzcGxpdCA9ICIgOiAiKSlbMV0NCiAgDQogIHJlc3VsdF9saXN0IDwtIGFkb25pc19wb3N0YW5hbHlzaXMoeD1wYWlyd2lzZV9kZiwNCiAgICAgICAgICAgICAgICAgICAgICBmYWN0b3JzID0gZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGUgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJENvdW50cnksIA0KICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMSA9IGdyb3VwMSwNCiAgICAgICAgICAgICAgICAgICAgICBncm91cDIgPSBncm91cDIsDQogICAgICAgICAgICAgICAgICAgICAgcGF0aWVudHMgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJFBhdGllbnQpDQogIHByaW50KHJlc3VsdF9saXN0KQ0KfSANCn0NCg0KYGBgDQoNCiMjIyMjIFBsb3RzDQoNCioqUENvQSBjdXN0b20qKg0KDQpgYGB7cn0NCnAgPC0gcGNhX3Bsb3RfY3VzdG9tKGZpbHRfY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9nZW51c190YXhhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfYm94cGxvdHMgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUgPSAiR3JvdXAiLCBzaXplPTIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19sZWdlbmQ9RkFMU0UpDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KcGNhX3Bsb3RzX2xpc3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsImN1c3RvbSIpXV0gPC0gcA0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcA0KDQpgYGANCg0KYGBge3IscmVzdWx0cz0naGlkZSd9DQpwZGYoIi4uL2ZpZ3VyZXMvUTIvYmV0YV9kaXZlcnNpdHlfY29sb24ucGRmIiwNCiAgICBoZWlnaHQgPTUsd2lkdGggPSA1KQ0KcA0KZGV2Lm9mZigpDQpgYGANCg0KIyMjIyBTYXZpbmcgcmVzdWx0cw0KDQpgYGB7cn0NCndyaXRlLnhsc3gocGFpcndpc2VfYWl0Y2hpc29uX3Jhd1tbcGFzdGUobGV2ZWwsIHNlZ21lbnQpXV0sIA0KICAgICAgICAgICBmaWxlID0gZmlsZS5wYXRoKHBhdGgsDQogICAgICAgICAgIHBhc3RlMCgiYmV0YV9kaXZlcnNpdHlfcmVzdWx0c18iLCBzZWdtZW50LCIueGxzeCIpKSkNCmBgYA0KDQojIyMgU3VwcGxlbWVudGFyeSBhbmFseXNpcw0KDQojIyMjIEdlbnVzIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9ImdlbnVzIg0KYGBgDQoNCiMjIyMjIEJyYXktQ3VydGlzDQoNCioqUEVSTUFOT1ZBKioNCg0KYGBge3J9DQpwYWlyd2lzZV9kZiA8LSBmaWx0X2NvbG9uX2dlbnVzX3RhYiAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJTZXFJRCIpICU+JSB0KCkNCg0KIyBtYWluIGVmZmVjdA0KcHBfbWFpbiA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSRDb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnRzID0gZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSRQYXRpZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltLm1ldGhvZCA9ICJicmF5IiwgcC5hZGp1c3QubT0iQkgiKQ0KDQojIGludGVyYWN0aW9uDQpwcF9pbnQgPC0gcGFpcndpc2UuYWRvbmlzKHBhaXJ3aXNlX2RmLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGUgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJENvdW50cnksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50cyA9IGZpbHRfY29sb25fZ2VudXNfbWV0YWRhdGEkUGF0aWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJhY3Rpb24gPSBUUlVFLCBzaW0ubWV0aG9kID0gImJyYXkiLCBwLmFkanVzdC5tPSJCSCIpDQoNCiMgdGlkeSB0aGUgcmVzdWx0cw0KcHBfZmFjdG9yIDwtIHBwX21haW5bWzFdXQ0KcHBfY292IDwtIHBwX21haW5bWzJdXQ0KcHBfZmFjLmNvdiA8LSBwcF9pbnRbWzNdXQ0KDQpjb2xzIDwtIGMoInBhaXJzIiwiRGYiLCJTdW1zT2ZTcXMiLCAiRi5Nb2RlbCIsIlIyIiwicC52YWx1ZSIsICJwLmFkanVzdGVkIiwgInNpZyIpDQpjb2xuYW1lcyhwcF9mYWN0b3IpIDwtIGNvbHM7IGNvbG5hbWVzKHBwX2NvdikgPC0gY29sczsgY29sbmFtZXMocHBfZmFjLmNvdikgPC0gY29sczsgDQoNCiMgc2F2ZSByYXcgcmVzdWx0cw0Kc3VwcGxlbWVudHNfYmV0YVtbcGFzdGUoImJyYXkiLGxldmVsLHNlZ21lbnQpXV0gPC0gcmJpbmQocHBfZmFjdG9yLHBwX2NvdixwcF9mYWMuY292KQ0KYGBgDQoNCmBgYHtyfQ0KIyBzZWUgdGhlIHJlc3VsdHMNCmtuaXRyOjprYWJsZShwcF9mYWN0b3IsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgR1JPVVAgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIENPVU5UUlkgc2VwYXJhdGlvbiIpDQprbml0cjo6a2FibGUocHBfZmFjLmNvdixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBJTlRFUkFDVElPTiBHUk9VUDpDb3VudHJ5IikNCmBgYA0KDQpJbnRlcmFjdGlvbiBjaGVjaw0KDQpgYGB7cn0NCmludGVyYWN0aW9uX3NpZyA8LSBwcF9mYWMuY292JHBhaXJzW3BwX2ZhYy5jb3YkcC5hZGp1c3RlZCA8IDAuMDVdDQoNCmZvciAoaSBpbiAxOmxlbmd0aChpbnRlcmFjdGlvbl9zaWcpKXsNCiAgZ3JvdXAxIDwtIHVubGlzdChzdHJzcGxpdChpbnRlcmFjdGlvbl9zaWdbaV0sc3BsaXQgPSAiIHZzICIpKVsxXQ0KICBncm91cDIgPC0gdW5saXN0KHN0cnNwbGl0KGludGVyYWN0aW9uX3NpZ1tpXSxzcGxpdCA9ICIgdnMgIikpWzJdDQogIGdyb3VwMiA8LSB1bmxpc3Qoc3Ryc3BsaXQoZ3JvdXAyLHNwbGl0ID0gIiA6ICIpKVsxXQ0KICANCiAgcmVzdWx0X2xpc3QgPC0gYWRvbmlzX3Bvc3RhbmFseXNpcyh4PXBhaXJ3aXNlX2RmLA0KICAgICAgICAgICAgICAgICAgICAgIGZhY3RvcnMgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfY29sb25fZ2VudXNfbWV0YWRhdGEkQ291bnRyeSwgDQogICAgICAgICAgICAgICAgICAgICAgcGF0aWVudHMgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJFBhdGllbnQsDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAxID0gZ3JvdXAxLA0KICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMiA9IGdyb3VwMiwNCiAgICAgICAgICAgICAgICAgICAgICBzaW0ubWV0aG9kID0gJ2JyYXknKQ0KICBwcmludChyZXN1bHRfbGlzdCkNCn0NCg0KYGBgDQoNCioqUGxvdHMqKg0KDQpgYGB7cn0NCnAgPC0gcGNhX3Bsb3RfY3VzdG9tKGZpbHRfY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9nZW51c190YXhhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPSAiYnJheSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2JveHBsb3RzID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlID0gIkdyb3VwIiwgc2l6ZT0zLCBzaG93X2xlZ2VuZD1GQUxTRSkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiUENvQSBicmF5IixsZXZlbCxzZWdtZW50KV1dIDwtIHANCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnANCmBgYA0KDQojIyMjIyBKYWNjYXJkDQoNCioqUEVSTUFOT1ZBKioNCg0KYGBge3J9DQpwYWlyd2lzZV9kZiA8LSBmaWx0X2NvbG9uX2dlbnVzX3RhYiAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJTZXFJRCIpICU+JSB0KCkNCg0KIyBtYWluIGVmZmVjdA0KcHBfbWFpbiA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSRDb3VudHJ5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudHMgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJFBhdGllbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaW0ubWV0aG9kID0gImphY2NhcmQiLCBwLmFkanVzdC5tPSJCSCIpDQoNCiMgaW50ZXJhY3Rpb24NCnBwX2ludCA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fZ2VudXNfbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfY29sb25fZ2VudXNfbWV0YWRhdGEkQ291bnRyeSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudHMgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJFBhdGllbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uID0gVFJVRSwgc2ltLm1ldGhvZCA9ICJqYWNjYXJkIiwgcC5hZGp1c3QubT0iQkgiKQ0KDQojIHRpZHkgdGhlIHJlc3VsdHMNCnBwX2ZhY3RvciA8LSBwcF9tYWluW1sxXV0NCnBwX2NvdiA8LSBwcF9tYWluW1syXV0NCnBwX2ZhYy5jb3YgPC0gcHBfaW50W1szXV0NCg0KY29scyA8LSBjKCJwYWlycyIsIkRmIiwiU3Vtc09mU3FzIiwgIkYuTW9kZWwiLCJSMiIsInAudmFsdWUiLCAicC5hZGp1c3RlZCIsICJzaWciKQ0KY29sbmFtZXMocHBfZmFjdG9yKSA8LSBjb2xzOyBjb2xuYW1lcyhwcF9jb3YpIDwtIGNvbHM7IGNvbG5hbWVzKHBwX2ZhYy5jb3YpIDwtIGNvbHM7IA0KDQojIHNhdmUgcmF3IHJlc3VsdHMNCnN1cHBsZW1lbnRzX2JldGFbW3Bhc3RlKCJqYWNjYXJkIixsZXZlbCxzZWdtZW50KV1dIDwtIHJiaW5kKHBwX2ZhY3RvciwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcF9jb3YsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHBfZmFjLmNvdikNCmBgYA0KDQpgYGB7cn0NCiMgc2VlIHRoZSByZXN1bHRzDQprbml0cjo6a2FibGUocHBfZmFjdG9yLGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIEdST1VQIHNlcGFyYXRpb24iKQ0Ka25pdHI6OmthYmxlKHBwX2NvdixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBDT1VOVFJZIHNlcGFyYXRpb24iKQ0Ka25pdHI6OmthYmxlKHBwX2ZhYy5jb3YsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgSU5URVJBQ1RJT04gR1JPVVA6Q291bnRyeSIpDQpgYGANCg0KSW50ZXJhY3Rpb24gY2hlY2sNCg0KYGBge3J9DQppbnRlcmFjdGlvbl9zaWcgPC0gcHBfZmFjLmNvdiRwYWlyc1twcF9mYWMuY292JHAuYWRqdXN0ZWQgPCAwLjA1XQ0KDQpmb3IgKGkgaW4gMTpsZW5ndGgoaW50ZXJhY3Rpb25fc2lnKSl7DQogIGdyb3VwMSA8LSB1bmxpc3Qoc3Ryc3BsaXQoaW50ZXJhY3Rpb25fc2lnW2ldLHNwbGl0ID0gIiB2cyAiKSlbMV0NCiAgZ3JvdXAyIDwtIHVubGlzdChzdHJzcGxpdChpbnRlcmFjdGlvbl9zaWdbaV0sc3BsaXQgPSAiIHZzICIpKVsyXQ0KICBncm91cDIgPC0gdW5saXN0KHN0cnNwbGl0KGdyb3VwMixzcGxpdCA9ICIgOiAiKSlbMV0NCiAgDQogIHJlc3VsdF9saXN0IDwtIGFkb25pc19wb3N0YW5hbHlzaXMoeD1wYWlyd2lzZV9kZiwNCiAgICAgICAgICAgICAgICAgICAgICBmYWN0b3JzID0gZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGUgPSBmaWx0X2NvbG9uX2dlbnVzX21ldGFkYXRhJENvdW50cnksIA0KICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnRzID0gZmlsdF9jb2xvbl9nZW51c19tZXRhZGF0YSRQYXRpZW50LA0KICAgICAgICAgICAgICAgICAgICAgIGdyb3VwMSA9IGdyb3VwMSwNCiAgICAgICAgICAgICAgICAgICAgICBncm91cDIgPSBncm91cDIsDQogICAgICAgICAgICAgICAgICAgICAgc2ltLm1ldGhvZCA9ICdqYWNjYXJkJykNCiAgcHJpbnQocmVzdWx0X2xpc3QpDQp9DQoNCmBgYA0KDQoqKlBsb3RzKioNCg0KKkN1c3RvbSoNCg0KYGBge3J9DQpwIDwtIHBjYV9wbG90X2N1c3RvbShmaWx0X2NvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fZ2VudXNfdGF4YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fZ2VudXNfbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFzdXJlID0gImphY2NhcmQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19ib3hwbG90cyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZSA9ICJHcm91cCIsIHNpemU9Mywgc2hvd19sZWdlbmQ9RkFMU0UpDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfYmV0YVtbcGFzdGUoIlBDb0EgamFjY2FyZCIsbGV2ZWwsc2VnbWVudCldXSA8LSBwDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpwDQpgYGANCg0KIyMjIyBBU1YgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iQVNWIg0KYGBgDQoNCiMjIyMjIEFpdGNoaXNvbg0KDQpgYGB7cn0NCiMgcHJlcGFyaW5nIGRhdGEgZnJhbWUNCnBhaXJ3aXNlX2RmIDwtIGZpbHRfY29sb25fYXN2X3RhYiAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJTZXFJRCIpICU+JSB0KCkNCg0KIyBtYWluIGVmZmVjdA0KcHBfbWFpbiA8LSBwYWlyd2lzZS5hZG9uaXMoeD1wYWlyd2lzZV9kZiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9tZXRhZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfY29sb25fbWV0YWRhdGEkQ291bnRyeSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaW0ubWV0aG9kID0gInJvYnVzdC5haXRjaGlzb24iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHAuYWRqdXN0Lm09IkJIIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnRzID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRQYXRpZW50KQ0KDQojIGludGVyYWN0aW9uDQpwcF9pbnQgPC0gcGFpcndpc2UuYWRvbmlzKHBhaXJ3aXNlX2RmLGZpbHRfY29sb25fbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfY29sb25fbWV0YWRhdGEkQ291bnRyeSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHNpbS5tZXRob2QgPSAicm9idXN0LmFpdGNoaXNvbiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwLmFkanVzdC5tPSJCSCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnRzID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRQYXRpZW50KQ0KDQpwcF9mYWN0b3IgPC0gcHBfbWFpbltbMV1dDQpwcF9jb3YgPC0gcHBfbWFpbltbMl1dDQpwcF9mYWMuY292IDwtIHBwX2ludFtbM11dDQoNCmNvbHMgPC0gYygicGFpcnMiLCJEZiIsIlN1bXNPZlNxcyIsICJGLk1vZGVsIiwiUjIiLCJwLnZhbHVlIiwgInAuYWRqdXN0ZWQiLCAic2lnIikNCmNvbG5hbWVzKHBwX2ZhY3RvcikgPC0gY29sczsgY29sbmFtZXMocHBfY292KSA8LSBjb2xzOyBjb2xuYW1lcyhwcF9mYWMuY292KSA8LSBjb2xzOyANCg0KIyBzYXZlIHJhdyByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiYWl0Y2hpc29uIixsZXZlbCxzZWdtZW50KV1dIDwtIHJiaW5kKHBwX2ZhY3RvciwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcF9jb3YsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHBfZmFjLmNvdikNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnBwX2ZhY3Rvcg0KcHBfY292DQpwcF9mYWMuY292DQoNCmBgYA0KDQpgYGB7cn0NCiMgc2VlIHRoZSByZXN1bHRzDQprbml0cjo6a2FibGUocHBfZmFjdG9yLGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIEdST1VQIHNlcGFyYXRpb24iKQ0Ka25pdHI6OmthYmxlKHBwX2NvdixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBDT1VOVFJZIHNlcGFyYXRpb24iKQ0Ka25pdHI6OmthYmxlKHBwX2ZhYy5jb3YsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgSU5URVJBQ1RJT04gR1JPVVA6Q291bnRyeSIpDQpgYGANCg0KSW50ZXJhY3Rpb24gY2hlY2sNCg0KYGBge3J9DQppbnRlcmFjdGlvbl9zaWcgPC0gcHBfZmFjLmNvdiRwYWlyc1twcF9mYWMuY292JHAuYWRqdXN0ZWQgPCAwLjA1XQ0KDQppZiAobGVuZ3RoKGludGVyYWN0aW9uX3NpZyk+MCl7DQogZm9yIChpIGluIDE6bGVuZ3RoKGludGVyYWN0aW9uX3NpZykpew0KICBncm91cDEgPC0gdW5saXN0KHN0cnNwbGl0KGludGVyYWN0aW9uX3NpZ1tpXSxzcGxpdCA9ICIgdnMgIikpWzFdDQogIGdyb3VwMiA8LSB1bmxpc3Qoc3Ryc3BsaXQoaW50ZXJhY3Rpb25fc2lnW2ldLHNwbGl0ID0gIiB2cyAiKSlbMl0NCiAgZ3JvdXAyIDwtIHVubGlzdChzdHJzcGxpdChncm91cDIsc3BsaXQgPSAiIDogIikpWzFdDQogIA0KICByZXN1bHRfbGlzdCA8LSBhZG9uaXNfcG9zdGFuYWx5c2lzKHg9cGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycyA9IGZpbHRfY29sb25fbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRDb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICBncm91cDEgPSBncm91cDEsDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAyID0gZ3JvdXAyLA0KICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnRzID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRQYXRpZW50KQ0KICBwcmludChyZXN1bHRfbGlzdCkNCn0gDQp9DQpgYGANCg0KKipQQ29BKioNCg0KYGBge3J9DQpwIDwtIHBjYV9wbG90X2N1c3RvbShmaWx0X2NvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfYm94cGxvdHMgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUgPSAiR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9MywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2xlZ2VuZD1GQUxTRSkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiUENvQSBhaXRjaGlzb24iLGxldmVsLHNlZ21lbnQpXV0gPC0gcA0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcA0KYGBgDQoNCiMjIyMjIEJyYXktQ3VydGlzIA0KDQoqUEVSTUFOT1ZBKg0KDQpgYGB7cn0NCiMgcHJlcGFyaW5nIGRhdGEgZnJhbWUNCnBhaXJ3aXNlX2RmIDwtIGZpbHRfY29sb25fYXN2X3RhYiAlPiUgY29sdW1uX3RvX3Jvd25hbWVzKCJTZXFJRCIpICU+JSB0KCkNCg0KIyBtYWluIGVmZmVjdA0KcHBfbWFpbiA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX21ldGFkYXRhJEdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRDb3VudHJ5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudHMgPSBmaWx0X2NvbG9uX21ldGFkYXRhJFBhdGllbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzaW0ubWV0aG9kID0gImJyYXkiLCBwLmFkanVzdC5tPSJCSCIpDQoNCiMgaW50ZXJhY3Rpb24NCnBwX2ludCA8LSBwYWlyd2lzZS5hZG9uaXMocGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9IGZpbHRfY29sb25fbWV0YWRhdGEkQ291bnRyeSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnRzID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRQYXRpZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmFjdGlvbiA9IFRSVUUsIHNpbS5tZXRob2QgPSAiYnJheSIsIHAuYWRqdXN0Lm09IkJIIikNCg0KcHBfZmFjdG9yIDwtIHBwX21haW5bWzFdXQ0KcHBfY292IDwtIHBwX21haW5bWzJdXQ0KcHBfZmFjLmNvdiA8LSBwcF9pbnRbWzNdXQ0KDQpjb2xzIDwtIGMoInBhaXJzIiwiRGYiLCJTdW1zT2ZTcXMiLCAiRi5Nb2RlbCIsIlIyIiwicC52YWx1ZSIsICJwLmFkanVzdGVkIiwgInNpZyIpDQpjb2xuYW1lcyhwcF9mYWN0b3IpIDwtIGNvbHM7IGNvbG5hbWVzKHBwX2NvdikgPC0gY29sczsgY29sbmFtZXMocHBfZmFjLmNvdikgPC0gY29sczsgDQoNCiMgc2F2ZSByYXcgcmVzdWx0cw0Kc3VwcGxlbWVudHNfYmV0YVtbcGFzdGUoImJyYXkiLGxldmVsLHNlZ21lbnQpXV0gPC0gcmJpbmQocHBfZmFjdG9yLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBwX2NvdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcF9mYWMuY292KQ0KDQpgYGANCg0KYGBge3J9DQojIHNlZSB0aGUgcmVzdWx0cw0Ka25pdHI6OmthYmxlKHBwX2ZhY3RvcixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBHUk9VUCBzZXBhcmF0aW9uIikNCmtuaXRyOjprYWJsZShwcF9jb3YsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgQ09VTlRSWSBzZXBhcmF0aW9uIikNCmtuaXRyOjprYWJsZShwcF9mYWMuY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIElOVEVSQUNUSU9OIEdST1VQOkNvdW50cnkiKQ0KYGBgDQoNCkludGVyYWN0aW9uIGNoZWNrDQoNCmBgYHtyfQ0KaW50ZXJhY3Rpb25fc2lnIDwtIHBwX2ZhYy5jb3YkcGFpcnNbcHBfZmFjLmNvdiRwLmFkanVzdGVkIDwgMC4wNV0NCg0KZm9yIChpIGluIDE6bGVuZ3RoKGludGVyYWN0aW9uX3NpZykpew0KICBncm91cDEgPC0gdW5saXN0KHN0cnNwbGl0KGludGVyYWN0aW9uX3NpZ1tpXSxzcGxpdCA9ICIgdnMgIikpWzFdDQogIGdyb3VwMiA8LSB1bmxpc3Qoc3Ryc3BsaXQoaW50ZXJhY3Rpb25fc2lnW2ldLHNwbGl0ID0gIiB2cyAiKSlbMl0NCiAgZ3JvdXAyIDwtIHVubGlzdChzdHJzcGxpdChncm91cDIsc3BsaXQgPSAiIDogIikpWzFdDQogIA0KICByZXN1bHRfbGlzdCA8LSBhZG9uaXNfcG9zdGFuYWx5c2lzKHg9cGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycyA9IGZpbHRfY29sb25fbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRDb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICBncm91cDEgPSBncm91cDEsDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAyID0gZ3JvdXAyLA0KICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnRzID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRQYXRpZW50LA0KICAgICAgICAgICAgICAgICAgICAgIHNpbS5tZXRob2QgPSAnYnJheScpDQogIHByaW50KHJlc3VsdF9saXN0KQ0KfQ0KDQpgYGANCg0KKipQQ29BKioNCg0KYGBge3J9DQpwIDwtIHBjYV9wbG90X2N1c3RvbShmaWx0X2NvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPSAiYnJheSIsDQogICAgICAgICAgICAgICAgICAgICBzaG93X2JveHBsb3RzID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlID0gIkdyb3VwIiwgc2l6ZT0zLCBzaG93X2xlZ2VuZD1GQUxTRSkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiUENvQSBicmF5IixsZXZlbCxzZWdtZW50KV1dIDwtIHANCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnANCmBgYA0KDQojIyMjIyBKYWNjYXJkDQoNCipQRVJNQU5PVkEqDQoNCmBgYHtyfQ0KIyBwcmVwYXJpbmcgZGF0YSBmcmFtZQ0KcGFpcndpc2VfZGYgPC0gZmlsdF9jb2xvbl9hc3ZfdGFiICU+JSBjb2x1bW5fdG9fcm93bmFtZXMoIlNlcUlEIikgJT4lIHQoKQ0KDQojIG1haW4gZWZmZWN0DQpwcF9tYWluIDwtIHBhaXJ3aXNlLmFkb25pcyhwYWlyd2lzZV9kZiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBjb3ZhcmlhdGUgPSBmaWx0X2NvbG9uX21ldGFkYXRhJENvdW50cnksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50cyA9IGZpbHRfY29sb25fbWV0YWRhdGEkUGF0aWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbS5tZXRob2QgPSAiamFjY2FyZCIsIHAuYWRqdXN0Lm09IkJIIikNCg0KIyBpbnRlcmFjdGlvbg0KcHBfaW50IDwtIHBhaXJ3aXNlLmFkb25pcyhwYWlyd2lzZV9kZiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9tZXRhZGF0YSRHcm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRDb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudHMgPSBmaWx0X2NvbG9uX21ldGFkYXRhJFBhdGllbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aW9uID0gVFJVRSwgc2ltLm1ldGhvZCA9ICJqYWNjYXJkIiwgcC5hZGp1c3QubT0iQkgiKQ0KDQpwcF9mYWN0b3IgPC0gcHBfbWFpbltbMV1dDQpwcF9jb3YgPC0gcHBfbWFpbltbMl1dDQpwcF9mYWMuY292IDwtIHBwX2ludFtbM11dDQoNCmNvbHMgPC0gYygicGFpcnMiLCJEZiIsIlN1bXNPZlNxcyIsICJGLk1vZGVsIiwiUjIiLCJwLnZhbHVlIiwgInAuYWRqdXN0ZWQiLCAic2lnIikNCmNvbG5hbWVzKHBwX2ZhY3RvcikgPC0gY29sczsgY29sbmFtZXMocHBfY292KSA8LSBjb2xzOyBjb2xuYW1lcyhwcF9mYWMuY292KSA8LSBjb2xzOyANCg0KIyBzYXZlIHJhdyByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiamFjY2FyZCIsbGV2ZWwsc2VnbWVudCldXSA8LSByYmluZChwcF9mYWN0b3IsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHBfY292LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBwX2ZhYy5jb3YpDQpgYGANCg0KYGBge3J9DQojIHNlZSB0aGUgcmVzdWx0cw0Ka25pdHI6OmthYmxlKHBwX2ZhY3RvcixkaWdpdHMgPSAzLGNhcHRpb24gPSAiUEVSTUFOT1ZBLCBHUk9VUCBzZXBhcmF0aW9uIikNCmtuaXRyOjprYWJsZShwcF9jb3YsZGlnaXRzID0gMyxjYXB0aW9uID0gIlBFUk1BTk9WQSwgQ09VTlRSWSBzZXBhcmF0aW9uIikNCmtuaXRyOjprYWJsZShwcF9mYWMuY292LGRpZ2l0cyA9IDMsY2FwdGlvbiA9ICJQRVJNQU5PVkEsIElOVEVSQUNUSU9OIEdST1VQOkNvdW50cnkiKQ0KYGBgDQoNCkludGVyYWN0aW9uIGNoZWNrDQoNCmBgYHtyfQ0KaW50ZXJhY3Rpb25fc2lnIDwtIHBwX2ZhYy5jb3YkcGFpcnNbcHBfZmFjLmNvdiRwLmFkanVzdGVkIDwgMC4wNV0NCg0KZm9yIChpIGluIDE6bGVuZ3RoKGludGVyYWN0aW9uX3NpZykpew0KICBncm91cDEgPC0gdW5saXN0KHN0cnNwbGl0KGludGVyYWN0aW9uX3NpZ1tpXSxzcGxpdCA9ICIgdnMgIikpWzFdDQogIGdyb3VwMiA8LSB1bmxpc3Qoc3Ryc3BsaXQoaW50ZXJhY3Rpb25fc2lnW2ldLHNwbGl0ID0gIiB2cyAiKSlbMl0NCiAgZ3JvdXAyIDwtIHVubGlzdChzdHJzcGxpdChncm91cDIsc3BsaXQgPSAiIDogIikpWzFdDQogIA0KICByZXN1bHRfbGlzdCA8LSBhZG9uaXNfcG9zdGFuYWx5c2lzKHg9cGFpcndpc2VfZGYsDQogICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycyA9IGZpbHRfY29sb25fbWV0YWRhdGEkR3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgY292YXJpYXRlID0gZmlsdF9jb2xvbl9tZXRhZGF0YSRDb3VudHJ5LCANCiAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50cyA9IGZpbHRfY29sb25fbWV0YWRhdGEkUGF0aWVudCwNCiAgICAgICAgICAgICAgICAgICAgICBncm91cDEgPSBncm91cDEsDQogICAgICAgICAgICAgICAgICAgICAgZ3JvdXAyID0gZ3JvdXAyLA0KICAgICAgICAgICAgICAgICAgICAgIHNpbS5tZXRob2QgPSAnamFjY2FyZCcpDQogIHByaW50KHJlc3VsdF9saXN0KQ0KfQ0KDQpgYGANCg0KKipQQ29BKioNCg0KYGBge3J9DQpwIDwtIHBjYV9wbG90X2N1c3RvbShmaWx0X2NvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgIG1lYXN1cmUgPSAiamFjY2FyZCIsDQogICAgICAgICAgICAgICAgICAgICBzaG93X2JveHBsb3RzID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlID0gIkdyb3VwIiwgc2l6ZT0zLCBzaG93X2xlZ2VuZD1GQUxTRSkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19iZXRhW1twYXN0ZSgiUENvQSBqYWNjYXJkIixsZXZlbCxzZWdtZW50KV1dIDwtIHANCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnANCmBgYA0KDQojIyMjIFNhdmluZyByZXN1bHRzDQoNCmBgYHtyfQ0Kd3JpdGUueGxzeChzdXBwbGVtZW50c19iZXRhWyFncmVwbCgiUENvQSIsbmFtZXMoc3VwcGxlbWVudHNfYmV0YSkpXSwNCiAgICAgICAgICAgZmlsZSA9IGZpbGUucGF0aChwYXRoLA0KICAgICAgICAgICBwYXN0ZTAoInN1cHBsZW1lbnRzX2JldGFfZGl2ZXJzaXR5XyIsIHNlZ21lbnQsIi54bHN4IikpKQ0KYGBgDQoNCiMjIFVuaXZhcmlhdGUgQW5hbHlzaXMNCg0KIyMjIE1haW4gLSBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpgYGB7cn0NCiMgbmVlZGVkIHBhdGhzDQpwYXRoID0gIi4uL3Jlc3VsdHMvUTIvdW5pdmFyaWF0ZV9hbmFseXNpcyINCnBhdGhfbWFhc2xpbj1maWxlLnBhdGgoIi4uL2ludGVybWVkaWF0ZV9maWxlcy9tYWFzbGluL1EyIixsZXZlbCkNCmBgYA0KDQpgYGB7cn0NCiMgdmFyaWFibGVzDQpyYXdfbGluZGFfcmVzdWx0c19nZW51c1tbc2VnbWVudF1dIDwtIGxpc3QoKQ0KbGluZGFfcmVzdWx0c19nZW51c1tbc2VnbWVudF1dIDwtIGxpc3QoKQ0KDQojIGNvdW50cnkgYW5kIGludGVyYWN0aW9uIHByb2JsZW1zDQpsaXN0X2NvdW50cnlfdW5pb24gPC0gbGlzdCgpDQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gbGlzdCgpDQpsaXN0X3Zlbm5zIDwtIGxpc3QoKQ0KdW5pX3N0YXRpc3RpY3MgPC0gbGlzdCgpDQoNCiMgd29ya2Jvb2sgZm9yIGZpbmFsIGRmDQp3YiA8LSBjcmVhdGVXb3JrYm9vaygpDQoNCiMgUFNDIGVmZmVjdA0KcnBzY19lZmZlY3QgPC0gbGlzdCgpDQpgYGANCg0KIyMjIyBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpBZ2dyZWdhdGUgdGF4YQ0KDQpgYGB7cn0NCmdlbnVzX2RhdGEgPC0gYWdncmVnYXRlX3RheGEoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheG9ub21pY19sZXZlbCA9IGxldmVsKQ0KDQpjb2xvbl9nZW51c190YWIgPC0gZ2VudXNfZGF0YVtbMV1dDQpjb2xvbl9nZW51c190YXhhX3RhYiA8LSBnZW51c19kYXRhW1syXV0NCg0KY29sb25fZ2VudXNfYXN2X3RheGFfdGFiIDwtIGNyZWF0ZV9hc3ZfdGF4YV90YWJsZShjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiKQ0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgbm9uLXJQU0MNCg0KIyMjIyMjIGxpbkRBDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJyUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpsaW5kYV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9jb2xvbl91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfY29sb25fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgIGZvcm11bGEgPSAnfiBHcm91cCAqIENvdW50cnkgKyAoMXxQYXRpZW50KScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpncm91cDEgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSkNCmdyb3VwMiA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgLCAiLGdyb3VwWzJdLCAiIC0gQ1ogdnMgTk8iKSANCmdyb3VwMyA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdLCAiOkNvdW50cnlOTyIpDQoNCg0KZm9yIChncnAgaW4gYyhncm91cDEsZ3JvdXAyLGdyb3VwMykpew0KICByYXdfbGluZGFfcmVzdWx0c19nZW51c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICByYXdsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfdGF4YSkNCiAgDQogIGxpbmRhX3Jlc3VsdHNfZ2VudXNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgbGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX3RheGEpDQp9DQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZShncm91cCxjb2xsYXBzZT0iIHZzICIpKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKSANCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCiMgc2VlIHRoZSBwbG90DQp2b2xjYW5vDQpgYGANCg0KIyMjIyMjIE1hQXNMaW4yDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmZpdF9kYXRhID0gTWFhc2xpbjIoDQogICAgaW5wdXRfZGF0YSA9IGZpbHRfY29sb25fdW5pX2RhdGEsIA0KICAgIGlucHV0X21ldGFkYXRhID0gZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsIG1pbl9hYnVuZGFuY2UgPSAwLA0KICAgIG1pbl9wcmV2YWxlbmNlID0gMCxtaW5fdmFyaWFuY2UgPSAwLA0KICAgIG91dHB1dCA9IGZpbGUucGF0aChwYXRoX21hYXNsaW4sZ3JvdXAxKSwgbWF4X3NpZ25pZmljYW5jZSA9IDAuMDUsDQogICAgZml4ZWRfZWZmZWN0cyA9IGMoJ0dyb3VwJywgJ0NvdW50cnknKSxyYW5kb21fZWZmZWN0cyA9ICJQYXRpZW50IiwNCiAgICBjb3JyZWN0aW9uID0gIkJIIikNCg0KYGBgDQoNCmBgYHtyfQ0Kdm9sY2FubzEgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9jb2xvbl91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUocGFzdGUoZ3JvdXBbMV0sICJ2cyIsIGdyb3VwWzJdKSkNCg0Kdm9sY2FubzIgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9jb2xvbl91bmlfdGF4YSx2YXJpYWJsZT0iQ291bnRyeSIpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQp2b2xjYW5vDQpgYGANCg0KIyMjIyMjIEdyb3VwIC0gSW50ZXJzZWN0aW9uDQoNCmBgYHtyfQ0KaW50ZXJzZWN0aW9uX3Jlc3VsdHMgPC0gZ3JvdXBfaW50ZXJzZWN0aW9uKGdyb3VwLCBsaXN0X2ludGVyc2VjdGlvbnMsIGxpc3RfdmVubnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0c19nZW51cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMV1dDQpsaXN0X3Zlbm5zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1syXV0NCnZlbm4gPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzNdXQ0KDQojIHNob3cgdGhlIHJlc3VsdHMNCnZlbm4NCmBgYA0KDQojIyMjIyMgQ291bnRyeSAtIFVuaW9uDQoNCmBgYHtyLGV2YWw9RkFMU0V9DQpsaXN0X2NvdW50cnlfdW5pb24gPC0gY291bnRyeV91bmlvbihncm91cCxsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIyMjIyMjIEludGVyYWN0aW9uIGVmZmVjdA0KDQpgYGB7cn0NCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQgPC0gY291bnRyeV9pbnRlcmFjdGlvbihncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQojIHNlZSB0aGUgcmVzdWx0DQojIyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBlZmZlY3QNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzFdXQ0KDQojIyByZXN1bHRzIGZvciBjemVjaCBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzJdXQ0KDQojIyByZXN1bHRzIGZvciBub3J3ZWdpYW4gY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1szXV0NCmBgYA0KDQpSZW1vdmluZyBwcm9ibGVtYXRpYyB0YXhhDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIHJlbW92aW5nX2ludGVyYWN0aW9uX3Byb2JsZW1zKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQojIyMjIyBCYXNpYyBzdGF0aXN0aWNzDQoNCmBgYHtyfQ0KdW5pX2RmIDwtICBtZXJnZShiYXNpY191bml2YXJpYXRlX3N0YXRpc3RpY3MobGluZGFfZGF0YSxncm91cCksDQogICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dyb3VwMV1dLA0KICAgICAgICAgICAgICAgICBieT0iU2VxSUQiLGFsbD1UUlVFKQ0KDQp1bmlfZGZbWyJmaW5hbF9zaWciXV0gPC0gdW5pX2RmJFNlcUlEICVpbiUgbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLGNvbXBhcmlzb25fbmFtZSldXVtbIlNlcUlEIl1dDQp1bmlfc3RhdGlzdGljc1tbc2VnbWVudF1dW1twYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpXV0gPC0gdW5pX2RmDQoNCiMgZm9yIGNvbXBhcmlzb24NCm5ld19uYW1lIDwtIGNvbXBhcmlzb25fbmFtZQ0KYWRkV29ya3NoZWV0KHdiLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YSh3Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIHJQU0MgdnMgaGVhbHRoeQ0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoImhlYWx0aHkiLCJyUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQojIyMjIyBsaW5EQQ0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpsaW5kYV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9jb2xvbl91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfY29sb25fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgIGZvcm11bGEgPSAnfiBHcm91cCAqIENvdW50cnkgKyAoMXxQYXRpZW50KScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpncm91cDEgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSkNCmdyb3VwMiA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgLCAiLGdyb3VwWzJdLCAiIC0gQ1ogdnMgTk8iKSANCmdyb3VwMyA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdLCAiOkNvdW50cnlOTyIpDQoNCmZvciAoZ3JwIGluIGMoZ3JvdXAxLGdyb3VwMixncm91cDMpKXsNCiAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgcmF3bGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX3RheGEpDQogIA0KICBsaW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIGxpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV90YXhhKQ0KfQ0KDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZShncm91cCxjb2xsYXBzZT0iIHZzICIpKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKSANCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCiMgc2VlIHRoZSBwbG90DQp2b2xjYW5vDQpgYGANCg0KIyMjIyMjIE1hQXNMaW4yDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmZpdF9kYXRhID0gTWFhc2xpbjIoDQogICAgaW5wdXRfZGF0YSA9IGZpbHRfY29sb25fdW5pX2RhdGEsIA0KICAgIGlucHV0X21ldGFkYXRhID0gZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsIG1pbl9hYnVuZGFuY2UgPSAwLA0KICAgIG1pbl9wcmV2YWxlbmNlID0gMCxtaW5fdmFyaWFuY2UgPSAwLA0KICAgIG91dHB1dCA9IGZpbGUucGF0aChwYXRoX21hYXNsaW4sZ3JvdXAxKSwgbWF4X3NpZ25pZmljYW5jZSA9IDAuMDUsDQogICAgZml4ZWRfZWZmZWN0cyA9IGMoJ0dyb3VwJywgJ0NvdW50cnknKSxyYW5kb21fZWZmZWN0cyA9ICJQYXRpZW50IiwNCiAgICBjb3JyZWN0aW9uID0gIkJIIikNCg0KYGBgDQoNCmBgYHtyfQ0Kdm9sY2FubzEgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9jb2xvbl91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUocGFzdGUoZ3JvdXBbMV0sICJ2cyIsIGdyb3VwWzJdKSkNCg0Kdm9sY2FubzIgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9jb2xvbl91bmlfdGF4YSx2YXJpYWJsZT0iQ291bnRyeSIpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQp2b2xjYW5vDQpgYGANCg0KIyMjIyMjIEdyb3VwIC0gSW50ZXJzZWN0aW9uDQoNCmBgYHtyfQ0KaW50ZXJzZWN0aW9uX3Jlc3VsdHMgPC0gZ3JvdXBfaW50ZXJzZWN0aW9uKGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfdmVubnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0c19nZW51cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMV1dDQpsaXN0X3Zlbm5zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1syXV0NCnZlbm4gPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzNdXQ0KDQojIHNob3cgdGhlIHJlc3VsdHMNCnZlbm4NCmBgYA0KDQojIyMjIyMgQ291bnRyeSAtIFVuaW9uDQoNCmBgYHtyLGV2YWw9RkFMU0V9DQpsaXN0X2NvdW50cnlfdW5pb24gPC0gY291bnRyeV91bmlvbihncm91cCxsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIyMjIyMjIEludGVyYWN0aW9uIGVmZmVjdA0KDQpgYGB7cn0NCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQgPC0gY291bnRyeV9pbnRlcmFjdGlvbihncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQojIHNlZSB0aGUgcmVzdWx0DQojIyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBlZmZlY3QNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzFdXQ0KDQojIyByZXN1bHRzIGZvciBjemVjaCBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzJdXQ0KDQojIyByZXN1bHRzIGZvciBub3J3ZWdpYW4gY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1szXV0NCmBgYA0KDQpSZW1vdmluZyBwcm9ibGVtYXRpYyB0YXhhDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIHJlbW92aW5nX2ludGVyYWN0aW9uX3Byb2JsZW1zKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQojIyMjIyBCYXNpYyBzdGF0aXN0aWNzDQoNCmBgYHtyfQ0KdW5pX2RmIDwtICBtZXJnZShiYXNpY191bml2YXJpYXRlX3N0YXRpc3RpY3MobGluZGFfZGF0YSxncm91cCksDQogICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dyb3VwMV1dLA0KICAgICAgICAgICAgICAgICBieT0iU2VxSUQiLGFsbD1UUlVFKQ0KDQp1bmlfZGZbWyJmaW5hbF9zaWciXV0gPC0gdW5pX2RmJFNlcUlEICVpbiUgbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLGNvbXBhcmlzb25fbmFtZSldXVtbIlNlcUlEIl1dDQp1bmlfc3RhdGlzdGljc1tbc2VnbWVudF1dW1twYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpXV0gPC0gdW5pX2RmDQoNCiMgZm9yIGNvbXBhcmlzb24NCm5ld19uYW1lIDwtIGNvbXBhcmlzb25fbmFtZQ0KYWRkV29ya3NoZWV0KHdiLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YSh3Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIyBub24tclBTQyB2cyBoZWFsdGh5DQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiaGVhbHRoeSIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQojIyMjIyMgbGluREENCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KbGluZGFfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSxncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9jb2xvbl91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfY29sb25fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgIGZvcm11bGEgPSAnfiBHcm91cCAqIENvdW50cnkgKyAoMXxQYXRpZW50KScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpncm91cDEgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSkNCmdyb3VwMiA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgLCAiLGdyb3VwWzJdLCAiIC0gQ1ogdnMgTk8iKSANCmdyb3VwMyA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdLCAiOkNvdW50cnlOTyIpDQoNCmZvciAoZ3JwIGluIGMoZ3JvdXAxLGdyb3VwMixncm91cDMpKXsNCiAgcmF3X2xpbmRhX3Jlc3VsdHNfZ2VudXNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgcmF3bGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX3RheGEpDQogIA0KICBsaW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIGxpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV90YXhhKQ0KfQ0KDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZShncm91cCxjb2xsYXBzZT0iIHZzICIpKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKSANCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCiMgc2VlIHRoZSBwbG90DQp2b2xjYW5vDQpgYGANCg0KIyMjIyMjIE1hQXNMaW4yDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmZpdF9kYXRhID0gTWFhc2xpbjIoDQogICAgaW5wdXRfZGF0YSA9IGZpbHRfY29sb25fdW5pX2RhdGEsIA0KICAgIGlucHV0X21ldGFkYXRhID0gZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsIG1pbl9hYnVuZGFuY2UgPSAwLA0KICAgIG1pbl9wcmV2YWxlbmNlID0gMCxtaW5fdmFyaWFuY2UgPSAwLA0KICAgIG91dHB1dCA9IGZpbGUucGF0aChwYXRoX21hYXNsaW4sZ3JvdXAxKSwgbWF4X3NpZ25pZmljYW5jZSA9IDAuMDUsDQogICAgZml4ZWRfZWZmZWN0cyA9IGMoJ0dyb3VwJywgJ0NvdW50cnknKSxyYW5kb21fZWZmZWN0cyA9ICJQYXRpZW50IiwNCiAgICBjb3JyZWN0aW9uID0gIkJIIikNCg0KDQpgYGANCg0KYGBge3J9DQp2b2xjYW5vMSA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZShncm91cFsxXSwgInZzIiwgZ3JvdXBbMl0pKQ0KDQp2b2xjYW5vMiA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2NvbG9uX3VuaV90YXhhLHZhcmlhYmxlPSJDb3VudHJ5IikgKyANCiAgICAgICAgICAgIGdndGl0bGUoIkNvdW50cnkgZWZmZWN0IikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2FubzEsdm9sY2FubzIsIG5jb2w9MikNCnZvbGNhbm8NCmBgYA0KDQojIyMjIyMgR3JvdXAgLSBJbnRlcnNlY3Rpb24NCg0KYGBge3J9DQppbnRlcnNlY3Rpb25fcmVzdWx0cyA8LSBncm91cF9pbnRlcnNlY3Rpb24oZ3JvdXAsIGxpc3RfaW50ZXJzZWN0aW9ucywgbGlzdF92ZW5ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50ID0gc2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1sxXV0NCmxpc3RfdmVubnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzJdXQ0KdmVubiA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbM11dDQoNCiMgc2hvdyB0aGUgcmVzdWx0cw0KdmVubg0KYGBgDQoNCiMjIyMjIyBDb3VudHJ5IC0gVW5pb24NCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpsaXN0X2NvdW50cnlfdW5pb24gPC0gY291bnRyeV91bmlvbihncm91cCxsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIyMjIyMjIEludGVyYWN0aW9uIGVmZmVjdA0KDQpgYGB7cn0NCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQgPC0gY291bnRyeV9pbnRlcmFjdGlvbihncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQojIHNlZSB0aGUgcmVzdWx0DQojIyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBlZmZlY3QNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzFdXQ0KDQojIyByZXN1bHRzIGZvciBjemVjaCBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzJdXQ0KDQojIyByZXN1bHRzIGZvciBub3J3ZWdpYW4gY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1szXV0NCmBgYA0KDQpSZW1vdmluZyBwcm9ibGVtYXRpYyB0YXhhDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIHJlbW92aW5nX2ludGVyYWN0aW9uX3Byb2JsZW1zKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQojIyMjIyBCYXNpYyBzdGF0aXN0aWNzDQoNCmBgYHtyfQ0KdW5pX2RmIDwtICBtZXJnZShiYXNpY191bml2YXJpYXRlX3N0YXRpc3RpY3MobGluZGFfZGF0YSxncm91cCksDQogICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzX2dlbnVzW1tzZWdtZW50XV1bW2dyb3VwMV1dLA0KICAgICAgICAgICAgICAgICBieT0iU2VxSUQiLGFsbD1UUlVFKQ0KDQp1bmlfZGZbWyJmaW5hbF9zaWciXV0gPC0gdW5pX2RmJFNlcUlEICVpbiUgbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLGNvbXBhcmlzb25fbmFtZSldXVtbIlNlcUlEIl1dDQp1bmlfc3RhdGlzdGljc1tbc2VnbWVudF1dW1twYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpXV0gPC0gdW5pX2RmDQoNCiMgZm9yIGNvbXBhcmlzb24NCm5ld19uYW1lIDwtIGNvbXBhcmlzb25fbmFtZQ0KYWRkV29ya3NoZWV0KHdiLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YSh3Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIyBWaXN1YWxpemF0aW9uDQoNCkhlYXRtYXAgdmlzdWFsaXppbmcgdGhlIGxpbkRBJ3MgbG9nRm9sZENoYW5nZSBmb3IgdGF4YSB3aXRoIHAgXDwgMC4xLg0KDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTE3LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpsaXN0X2hlYXRtYXAgPC0gbGlzdF9pbnRlcnNlY3Rpb25zW2dyZXAocGFzdGUoc2VnbWVudCxsZXZlbCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXMobGlzdF9pbnRlcnNlY3Rpb25zKSx2YWx1ZT1UUlVFKV0NCg0KcF9oZWF0bWFwX2xpbmRhIDwtIGhlYXRtYXBfbGluZGEobGlzdF9oZWF0bWFwLGNvbG9uX3RheGFfdGFiKQ0KcF9oZWF0bWFwX2xpbmRhDQpgYGANCg0KRG90IGhlYXRtYXANCg0KYGBge3IsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTE3LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpkb3RoZWF0bWFwX2xpbmRhIDwtIGRvdF9oZWF0bWFwX2xpbmRhKGxpc3RfaGVhdG1hcCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pX3N0YXRpc3RpY3MkY29sb25bZ3JlcGwobGV2ZWwsbmFtZXModW5pX3N0YXRpc3RpY3MkY29sb24pKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiKSArIHhsYWIoIiIpICsgeWxhYigiIikNCmRvdGhlYXRtYXBfbGluZGENCmBgYA0KDQoqKkhvcml6b250YWwgYmFyIHBsb3QqKg0KDQpgYGB7cn0NCnBfcHJldmFsZW5jZSA8LSBob3Jpem9udGFsX2JhcnBsb3Qod2IsdGF4YT1sZXZlbHMoZG90aGVhdG1hcF9saW5kYSRkYXRhJFNlcUlEKSkNCmBgYA0KDQoNCmBgYHtyfQ0KcF9wcmV2YWxlbmNlX2ZpbmFsIDwtIGdnYXJyYW5nZShwX3ByZXZhbGVuY2UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdncGxvdCgpICsgdGhlbWVfbWluaW1hbCgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBucm93ID0gMixoZWlnaHRzID0gYygxLDAuMDg1KSkNCnAgPC0gZ2dhcnJhbmdlKGRvdGhlYXRtYXBfbGluZGEgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpLHBfcHJldmFsZW5jZV9maW5hbCxuY29sPTIsd2lkdGhzID0gYygxLDAuMykpDQpwDQoNCmRvdF9oZWF0bWFwX2NvbG9uIDwtIHANCmBgYA0KDQpgYGB7cixyZXN1bHRzPSdoaWRlJ30NCnBkZigiLi4vZmlndXJlcy9RMi9kb3RwbG90X2NvbG9uLnBkZiIsDQogICAgaGVpZ2h0ID0xMCx3aWR0aCA9IDQpDQpwDQpkZXYub2ZmKCkNCmBgYA0KDQoNCiMjIyMjIHJQU0MgZWZmZWN0DQoNCioqcHJlX0xUeCB2cyBIZWFsdGh5IGFuZCBQb3N0X0xUeCB2cyBIZWFsdGh5IGludGVyc2VjdGlvbioqDQoNCg0KYGBge3J9DQpBIDwtIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCwiaGVhbHRoeSB2cyByUFNDIildXQ0KQiA8LSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsImhlYWx0aHkgdnMgbm9uLXJQU0MiKV1dDQpkZiA8LSBBWyEoQSRTZXFJRCAlaW4lIEIkU2VxSUQpLF0NCg0KcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0gPC0gZGYNCiAgDQojIHNlZSB0aGUgcmVzdWx0cw0KcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0gDQpgYGANCg0KIyMjIyBTYXZpbmcgcmVzdWx0cw0KDQpgYGB7cn0NCiMgQUxMIERBVEENCnNhdmVXb3JrYm9vayh3YixmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInVuaV9hbmFseXNpc193Yl8iLHNlZ21lbnQsIi54bHN4IikpLA0KICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IFRSVUUpDQoNCiMgUFNDIGVmZmVjdA0Kd3JpdGUueGxzeChycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSxmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInJwc2NfZWZmZWN0XyIsc2VnbWVudCwiLnhsc3giKSkpDQoNCiMgU0lHTklGSUNBTlQgdGF4YQ0KDQp3cml0ZS54bHN4KGxpc3RfaW50ZXJzZWN0aW9uc1tncmVwbChzZWdtZW50LG5hbWVzKGxpc3RfaW50ZXJzZWN0aW9ucykpXSAlPiUNCiAgICAgICAgICAgIGBuYW1lczwtYChnc3ViKHNlZ21lbnQsICIiLCBuYW1lcygNCiAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zW2dyZXBsKHNlZ21lbnQsbmFtZXMobGlzdF9pbnRlcnNlY3Rpb25zKSldKSkpLA0KICAgICAgICAgICBmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInNpZ25pZmljYW50X3RheGFfIixzZWdtZW50LCIueGxzeCIpKSkNCmBgYA0KDQojIyMgU3VwcGxlbWVudGFyeSBBbmFseXNpcw0KDQojIyMjIEFTViBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJBU1YiDQpgYGANCg0KYGBge3J9DQpwYXRoX21hYXNsaW49Ii4uL2ludGVybWVkaWF0ZV9maWxlcy9tYWFzbGluL1EyL0FTVi8iDQpgYGANCg0KYGBge3J9DQpyYXdfbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dIDwtIGxpc3QoKQ0KbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dIDwtIGxpc3QoKQ0Kc3VwcGxlbWVudHNfd2IgPC0gY3JlYXRlV29ya2Jvb2soKQ0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgbm9uLXJQU0MNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsInJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCioqbGluREEqKg0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpsaW5kYV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9ImxpbkRBIikNCg0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBsaW5kYV9kYXRhW1sxXV0NCmZpbHRfY29sb25fdW5pX3RheGEgPC0gbGluZGFfZGF0YVtbMl1dDQpmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSA8LSBsaW5kYV9kYXRhW1szXV0NCg0KIyBmaXQgdGhlIG1vZGVsDQpsaW5kYS5vYmogPC0gbGluZGEoZmlsdF9jb2xvbl91bmlfZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsIA0KICAgICAgICAgICAgICAgICAgIGZvcm11bGEgPSAnfiBHcm91cCAqIENvdW50cnkgKyAoMXxQYXRpZW50KScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KZ3JvdXAxIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0pDQpncm91cDIgPC0gcGFzdGUwKGdyb3VwWzFdLCAiICwgIixncm91cFsyXSwgIiAtIENaIHZzIE5PIikgDQpncm91cDMgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSwgIjpDb3VudHJ5Tk8iKQ0KDQpmb3IgKGdycCBpbiBjKGdyb3VwMSxncm91cDIsZ3JvdXAzKSl7DQogIHJhd19saW5kYV9yZXN1bHRzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIHJhd2xpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV90YXhhKQ0KICANCiAgbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICBsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfdGF4YSkNCn0NCg0KYGBgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KIyB2b2xjYW5vIHBsb3QNCnZvbGNhbm9fMSA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArDQogICAgICAgICAgICAgIGdndGl0bGUocGFzdGUoZ3JvdXAsY29sbGFwc2U9IiB2cyAiKSkNCg0Kdm9sY2Fub18yICA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfY29sb25fdW5pX3RheGEpICsgDQogICAgICAgICAgICAgIGdndGl0bGUoIkNvdW50cnkgZWZmZWN0IikNCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCiMgc2VlIHRoZSBwbG90DQp2b2xjYW5vDQpgYGANCg0KKipNYUFzTGluMioqDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmZpdF9kYXRhID0gTWFhc2xpbjIoDQogICAgaW5wdXRfZGF0YSA9IGZpbHRfY29sb25fdW5pX2RhdGEsIA0KICAgIGlucHV0X21ldGFkYXRhID0gZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsIG1pbl9hYnVuZGFuY2UgPSAwLA0KICAgIG1pbl9wcmV2YWxlbmNlID0gMCxtaW5fdmFyaWFuY2UgPSAwLA0KICAgIG91dHB1dCA9IGZpbGUucGF0aChwYXRoX21hYXNsaW4sZ3JvdXAxKSwgbWF4X3NpZ25pZmljYW5jZSA9IDAuMDUsDQogICAgZml4ZWRfZWZmZWN0cyA9IGMoJ0dyb3VwJywgJ0NvdW50cnknKSxyYW5kb21fZWZmZWN0cyA9ICJQYXRpZW50IiwNCiAgICBjb3JyZWN0aW9uID0gIkJIIikNCg0KYGBgDQoNClZvbGNhbm8gcGxvdA0KDQpgYGB7cn0NCnZvbGNhbm8xIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfY29sb25fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKHBhc3RlKGdyb3VwWzFdLCAidnMiLCBncm91cFsyXSkpDQoNCnZvbGNhbm8yIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfY29sb25fdW5pX3RheGEsdmFyaWFibGU9IkNvdW50cnkiKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQp2b2xjYW5vDQoNCmBgYA0KDQoqKkdyb3VwIC0gSW50ZXJzZWN0aW9uKioNCg0KYGBge3J9DQppbnRlcnNlY3Rpb25fcmVzdWx0cyA8LSBncm91cF9pbnRlcnNlY3Rpb24oZ3JvdXAsIGxpc3RfaW50ZXJzZWN0aW9ucywgbGlzdF92ZW5ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMV1dDQpsaXN0X3Zlbm5zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1syXV0NCnZlbm4gPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzNdXQ0KDQojIHNob3cgdGhlIHJlc3VsdHMNCnZlbm4NCmBgYA0KDQoqKkNvdW50cnkgLSBVbmlvbioqDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KbGlzdF9jb3VudHJ5X3VuaW9uIDwtIGNvdW50cnlfdW5pb24oZ3JvdXAsbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCioqSW50ZXJhY3Rpb24gZWZmZWN0KioNCg0KYGBge3J9DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50IDwtIGNvdW50cnlfaW50ZXJhY3Rpb24oZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KIyBzZWUgdGhlIHJlc3VsdA0KIyMgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gZWZmZWN0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1sxXV0NCg0KIyMgcmVzdWx0cyBmb3IgY3plY2ggY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1syXV0NCg0KIyMgcmVzdWx0cyBmb3Igbm9yd2VnaWFuIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbM11dDQpgYGANCg0KUmVtb3ZpbmcgcHJvYmxlbWF0aWMgdGF4YQ0KDQpgYGB7cn0NCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSByZW1vdmluZ19pbnRlcmFjdGlvbl9wcm9ibGVtcyhncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KQmFzaWMgc3RhdGlzdGljcw0KDQpgYGB7cn0NCnVuaV9kZiA8LSAgbWVyZ2UoYmFzaWNfdW5pdmFyaWF0ZV9zdGF0aXN0aWNzKGxpbmRhX2RhdGEsZ3JvdXApLA0KICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncm91cDFdXSwNCiAgICAgICAgICAgICAgICAgYnk9IlNlcUlEIixhbGw9VFJVRSkNCg0KdW5pX2RmW1siZmluYWxfc2lnIl1dIDwtIHVuaV9kZiRTZXFJRCAlaW4lIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCxjb21wYXJpc29uX25hbWUpXV1bWyJTZXFJRCJdXQ0KdW5pX3N0YXRpc3RpY3NbW3NlZ21lbnRdXVtbcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dIDwtIHVuaV9kZg0KDQojIGZvciBjb21wYXJpc29uDQpuZXdfbmFtZSA8LSBwYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpDQphZGRXb3Jrc2hlZXQoc3VwcGxlbWVudHNfd2IsIHNoZWV0TmFtZSA9IG5ld19uYW1lKQ0Kd3JpdGVEYXRhKHN1cHBsZW1lbnRzX3diLCBzaGVldCA9IG5ld19uYW1lLCB1bmlfZGYsIHJvd05hbWVzPUZBTFNFKQ0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgaGVhbHRoeQ0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoImhlYWx0aHkiLCJyUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQoqKmxpbkRBKioNCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KbGluZGFfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2Fzdl90YWIsY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsZ3JvdXAsIHVzYWdlPSJsaW5EQSIpDQoNCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gbGluZGFfZGF0YVtbMV1dDQpmaWx0X2NvbG9uX3VuaV90YXhhIDwtIGxpbmRhX2RhdGFbWzJdXQ0KZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEgPC0gbGluZGFfZGF0YVtbM11dDQoNCiMgZml0IHRoZSBtb2RlbA0KbGluZGEub2JqIDwtIGxpbmRhKGZpbHRfY29sb25fdW5pX2RhdGEsIA0KICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX21ldGFkYXRhLCANCiAgICAgICAgICAgICAgICAgICBmb3JtdWxhID0gJ34gR3JvdXAgKiBDb3VudHJ5ICsgKDF8UGF0aWVudCknKQ0KDQpsaW5kYS5vdXRwdXQgPC0gbGluZGEub2JqJG91dHB1dA0KbGluZGEub3V0cHV0IDwtIGxpbmRhX3JlbmFtaW5nKGxpbmRhLm91dHB1dCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KZ3JvdXAxIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0pDQpncm91cDIgPC0gcGFzdGUwKGdyb3VwWzFdLCAiICwgIixncm91cFsyXSwgIiAtIENaIHZzIE5PIikgDQpncm91cDMgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSwgIjpDb3VudHJ5Tk8iKQ0KDQpmb3IgKGdycCBpbiBjKGdyb3VwMSxncm91cDIsZ3JvdXAzKSl7DQogIHJhd19saW5kYV9yZXN1bHRzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIHJhd2xpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV90YXhhKQ0KICANCiAgbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICBsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfdGF4YSkNCn0NCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCiMgdm9sY2FubyBwbG90DQp2b2xjYW5vXzEgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9jb2xvbl91bmlfdGF4YSkgKw0KICAgICAgICAgICAgICBnZ3RpdGxlKHBhc3RlKGdyb3VwLGNvbGxhcHNlPSIgdnMgIikpDQoNCnZvbGNhbm9fMiAgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm9fMyA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9jb2xvbl91bmlfdGF4YSkgKyANCiAgICAgICAgICAgICAgZ2d0aXRsZSgiSW50ZXJhY3Rpb24iKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vXzEsdm9sY2Fub18yLHZvbGNhbm9fMywgbmNvbD0zKQ0KDQojIHNlZSB0aGUgcGxvdA0Kdm9sY2Fubw0KYGBgDQoNCioqTWFBc0xpbjIqKg0KDQpgYGB7ciwgZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJyxtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQpmaXRfZGF0YSA9IE1hYXNsaW4yKA0KICAgIGlucHV0X2RhdGEgPSBmaWx0X2NvbG9uX3VuaV9kYXRhLCANCiAgICBpbnB1dF9tZXRhZGF0YSA9IGZpbHRfY29sb25fdW5pX21ldGFkYXRhLCBtaW5fYWJ1bmRhbmNlID0gMCwNCiAgICBtaW5fcHJldmFsZW5jZSA9IDAsbWluX3ZhcmlhbmNlID0gMCwNCiAgICBvdXRwdXQgPSBmaWxlLnBhdGgocGF0aF9tYWFzbGluLGdyb3VwMSksIG1heF9zaWduaWZpY2FuY2UgPSAwLjA1LA0KICAgIGZpeGVkX2VmZmVjdHMgPSBjKCdHcm91cCcsICdDb3VudHJ5JykscmFuZG9tX2VmZmVjdHMgPSAiUGF0aWVudCIsDQogICAgY29ycmVjdGlvbiA9ICJCSCIpDQoNCmBgYA0KDQpgYGB7cn0NCnZvbGNhbm8xIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfY29sb25fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKHBhc3RlKGdyb3VwWzFdLCAidnMiLCBncm91cFsyXSkpDQoNCnZvbGNhbm8yIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfY29sb25fdW5pX3RheGEsdmFyaWFibGU9IkNvdW50cnkiKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQp2b2xjYW5vDQpgYGANCg0KKipHcm91cCAtIEludGVyc2VjdGlvbioqDQoNCmBgYHtyfQ0KaW50ZXJzZWN0aW9uX3Jlc3VsdHMgPC0gZ3JvdXBfaW50ZXJzZWN0aW9uKGdyb3VwLCBsaXN0X2ludGVyc2VjdGlvbnMsIGxpc3RfdmVubnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzFdXQ0KbGlzdF92ZW5ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMl1dDQp2ZW5uIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1szXV0NCg0KIyBzaG93IHRoZSByZXN1bHRzDQp2ZW5uDQpgYGANCg0KKipDb3VudHJ5IC0gVW5pb24qKg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmxpc3RfY291bnRyeV91bmlvbiA8LSBjb3VudHJ5X3VuaW9uKGdyb3VwLGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQoqKkludGVyYWN0aW9uIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCA8LSBjb3VudHJ5X2ludGVyYWN0aW9uKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCiMgc2VlIHRoZSByZXN1bHQNCiMjIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGVmZmVjdA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMV1dDQoNCiMjIHJlc3VsdHMgZm9yIGN6ZWNoIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMl1dDQoNCiMjIHJlc3VsdHMgZm9yIG5vcndlZ2lhbiBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzNdXQ0KYGBgDQoNClJlbW92aW5nIHByb2JsZW1hdGljIHRheGENCg0KYGBge3J9DQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gcmVtb3ZpbmdfaW50ZXJhY3Rpb25fcHJvYmxlbXMoZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQoqKkJhc2ljIHN0YXRpc3RpY3MqKg0KDQpgYGB7cn0NCnVuaV9kZiA8LSAgbWVyZ2UoYmFzaWNfdW5pdmFyaWF0ZV9zdGF0aXN0aWNzKGxpbmRhX2RhdGEsZ3JvdXApLA0KICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncm91cDFdXSwNCiAgICAgICAgICAgICAgICAgYnk9IlNlcUlEIixhbGw9VFJVRSkNCg0KdW5pX2RmW1siZmluYWxfc2lnIl1dIDwtIHVuaV9kZiRTZXFJRCAlaW4lIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCxjb21wYXJpc29uX25hbWUpXV1bWyJTZXFJRCJdXQ0KdW5pX3N0YXRpc3RpY3NbW3NlZ21lbnRdXVtbcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dIDwtIHVuaV9kZg0KDQojIGZvciBjb21wYXJpc29uDQpuZXdfbmFtZSA8LSBwYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpDQphZGRXb3Jrc2hlZXQoc3VwcGxlbWVudHNfd2IsIHNoZWV0TmFtZSA9IG5ld19uYW1lKQ0Kd3JpdGVEYXRhKHN1cHBsZW1lbnRzX3diLCBzaGVldCA9IG5ld19uYW1lLCB1bmlfZGYsIHJvd05hbWVzPUZBTFNFKQ0KYGBgDQoNCiMjIyMjIG5vbi1yUFNDIHZzIGhlYWx0aHkNCg0KYGBge3J9DQpncm91cCA8LSBjKCJoZWFsdGh5Iiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCioqbGluREEqKg0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpsaW5kYV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9ImxpbkRBIikNCg0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBsaW5kYV9kYXRhW1sxXV0NCmZpbHRfY29sb25fdW5pX3RheGEgPC0gbGluZGFfZGF0YVtbMl1dDQpmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSA8LSBsaW5kYV9kYXRhW1szXV0NCg0KIyBmaXQgdGhlIG1vZGVsDQpsaW5kYS5vYmogPC0gbGluZGEoZmlsdF9jb2xvbl91bmlfZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgZm9ybXVsYSA9ICd+IEdyb3VwICogQ291bnRyeSArICgxfFBhdGllbnQpJykNCg0KbGluZGEub3V0cHV0IDwtIGxpbmRhLm9iaiRvdXRwdXQNCmxpbmRhLm91dHB1dCA8LSBsaW5kYV9yZW5hbWluZyhsaW5kYS5vdXRwdXQsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCmdyb3VwMSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdKQ0KZ3JvdXAyIDwtIHBhc3RlMChncm91cFsxXSwgIiAsICIsZ3JvdXBbMl0sICIgLSBDWiB2cyBOTyIpIA0KZ3JvdXAzIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0sICI6Q291bnRyeU5PIikNCg0KZm9yIChncnAgaW4gYyhncm91cDEsZ3JvdXAyLGdyb3VwMykpew0KICByYXdfbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICByYXdsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfdGF4YSkNCiAgDQogIGxpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgbGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX3RheGEpDQp9DQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfY29sb25fdW5pX3RheGEpICsNCiAgICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZShncm91cCxjb2xsYXBzZT0iIHZzICIpKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9jb2xvbl91bmlfdGF4YSkgKyANCiAgICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKQ0KDQp2b2xjYW5vXzMgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfY29sb25fdW5pX3RheGEpICsgDQogICAgICAgICAgICAgIGdndGl0bGUoIkludGVyYWN0aW9uIikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2Fub18xLHZvbGNhbm9fMix2b2xjYW5vXzMsIG5jb2w9MykNCg0KIyBzZWUgdGhlIHBsb3QNCnZvbGNhbm8NCmBgYA0KDQoqKk1hQXNMaW4yKioNCg0KYGBge3IsIGVjaG89RkFMU0UscmVzdWx0cz0naGlkZScsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KZml0X2RhdGEgPSBNYWFzbGluMigNCiAgICBpbnB1dF9kYXRhID0gZmlsdF9jb2xvbl91bmlfZGF0YSwgDQogICAgaW5wdXRfbWV0YWRhdGEgPSBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwgbWluX2FidW5kYW5jZSA9IDAsDQogICAgbWluX3ByZXZhbGVuY2UgPSAwLG1pbl92YXJpYW5jZSA9IDAsDQogICAgb3V0cHV0ID0gZmlsZS5wYXRoKHBhdGhfbWFhc2xpbixncm91cDEpLCBtYXhfc2lnbmlmaWNhbmNlID0gMC4wNSwNCiAgICBmaXhlZF9lZmZlY3RzID0gYygnR3JvdXAnLCAnQ291bnRyeScpLHJhbmRvbV9lZmZlY3RzID0gIlBhdGllbnQiLA0KICAgIGNvcnJlY3Rpb24gPSAiQkgiKQ0KYGBgDQoNCmBgYHtyfQ0Kdm9sY2FubzEgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9jb2xvbl91bmlfdGF4YSkgKyANCiAgICAgICAgICAgIGdndGl0bGUocGFzdGUoZ3JvdXBbMV0sICJ2cyIsIGdyb3VwWzJdKSkNCg0Kdm9sY2FubzIgPC0gdm9sY2Fub19wbG90X21hYXNsaW4oZml0X2RhdGEsZmlsdF9jb2xvbl91bmlfdGF4YSx2YXJpYWJsZT0iQ291bnRyeSIpICsgDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQp2b2xjYW5vDQpgYGANCg0KKipHcm91cCAtIEludGVyc2VjdGlvbioqDQoNCmBgYHtyfQ0KaW50ZXJzZWN0aW9uX3Jlc3VsdHMgPC0gZ3JvdXBfaW50ZXJzZWN0aW9uKGdyb3VwLCBsaXN0X2ludGVyc2VjdGlvbnMsIGxpc3RfdmVubnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMV1dDQpsaXN0X3Zlbm5zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1syXV0NCnZlbm4gPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzNdXQ0KDQojIHNob3cgdGhlIHJlc3VsdHMNCnZlbm4NCmBgYA0KDQoqKkNvdW50cnkgLSBVbmlvbioqDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KbGlzdF9jb3VudHJ5X3VuaW9uIDwtIGNvdW50cnlfdW5pb24oZ3JvdXAsbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCioqSW50ZXJhY3Rpb24gZWZmZWN0KioNCg0KYGBge3J9DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50IDwtIGNvdW50cnlfaW50ZXJhY3Rpb24oZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KIyBzZWUgdGhlIHJlc3VsdA0KIyMgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gZWZmZWN0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1sxXV0NCg0KIyMgcmVzdWx0cyBmb3IgY3plY2ggY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1syXV0NCg0KIyMgcmVzdWx0cyBmb3Igbm9yd2VnaWFuIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbM11dDQpgYGANCg0KUmVtb3ZpbmcgcHJvYmxlbWF0aWMgdGF4YQ0KDQpgYGB7cn0NCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSByZW1vdmluZ19pbnRlcmFjdGlvbl9wcm9ibGVtcyhncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KIEJhc2ljIHN0YXRpc3RpY3MNCg0KYGBge3J9DQp1bmlfZGYgPC0gIG1lcmdlKGJhc2ljX3VuaXZhcmlhdGVfc3RhdGlzdGljcyhsaW5kYV9kYXRhLGdyb3VwKSwNCiAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JvdXAxXV0sDQogICAgICAgICAgICAgICAgIGJ5PSJTZXFJRCIsYWxsPVRSVUUpDQoNCnVuaV9kZltbImZpbmFsX3NpZyJdXSA8LSB1bmlfZGYkU2VxSUQgJWluJSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dW1siU2VxSUQiXV0NCnVuaV9zdGF0aXN0aWNzW1tzZWdtZW50XV1bW3Bhc3RlKGxldmVsLGNvbXBhcmlzb25fbmFtZSldXSA8LSB1bmlfZGYNCg0KIyBmb3IgY29tcGFyaXNvbg0KbmV3X25hbWUgPC0gcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKQ0KYWRkV29ya3NoZWV0KHN1cHBsZW1lbnRzX3diLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YShzdXBwbGVtZW50c193Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIyBWaXN1YWxpemF0aW9uDQoNCkhlYXRtYXAgdmlzdWFsaXppbmcgdGhlIGxpbkRBJ3MgbG9nRm9sZENoYW5nZSBmb3IgdGF4YSB3aXRoIHAgXDwgMC4xLg0KDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTE3LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpsaXN0X2hlYXRtYXAgPC0gbGlzdF9pbnRlcnNlY3Rpb25zW2dyZXAocGFzdGUoc2VnbWVudCxsZXZlbCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXMobGlzdF9pbnRlcnNlY3Rpb25zKSx2YWx1ZT1UUlVFKV0NCg0KcF9oZWF0bWFwX2xpbmRhIDwtIGhlYXRtYXBfbGluZGEobGlzdF9oZWF0bWFwLGNvbG9uX3RheGFfdGFiKQ0KcF9oZWF0bWFwX2xpbmRhDQpgYGANCg0KKipEb3QgaGVhdG1hcCoqDQoNCmBgYHtyLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD0yNSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KZG90aGVhdG1hcF9saW5kYSA8LSBkb3RfaGVhdG1hcF9saW5kYShsaXN0X2hlYXRtYXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaV9zdGF0aXN0aWNzJGNvbG9uW2dyZXBsKGxldmVsLG5hbWVzKHVuaV9zdGF0aXN0aWNzJGNvbG9uKSldLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYikNCmRvdGhlYXRtYXBfbGluZGENCmBgYA0KDQojIyMjIyByUFNDIGVmZmVjdA0KDQoqKnByZV9MVHggdnMgSGVhbHRoeSBhbmQgUG9zdF9MVHggdnMgSGVhbHRoeSBpbnRlcnNlY3Rpb24qKg0KDQoNCmBgYHtyfQ0KQSA8LSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsImhlYWx0aHkgdnMgclBTQyIpXV0NCkIgPC0gbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLCJoZWFsdGh5IHZzIG5vbi1yUFNDIildXQ0KZGYgPC0gQVshKEEkU2VxSUQgJWluJSBCJFNlcUlEKSxdDQoNCnJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dIDwtIGRmDQogIA0KIyBzZWUgdGhlIHJlc3VsdHMNCnJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dIA0KYGBgDQoNCiMjIyMgUGh5bHVtIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9InBoeWx1bSINCmBgYA0KDQpgYGB7cn0NCnBhdGhfbWFhc2xpbj0iLi4vaW50ZXJtZWRpYXRlX2ZpbGVzL21hYXNsaW4vUTIvUGh5bHVtLyINCmBgYA0KDQpgYGB7cn0NCnJhd19saW5kYV9yZXN1bHRzX3BoeWx1bVtbc2VnbWVudF1dIDwtIGxpc3QoKQ0KbGluZGFfcmVzdWx0c19waHlsdW1bW3NlZ21lbnRdXSA8LSBsaXN0KCkNCmBgYA0KDQpBZ2dyZWdhdGUgdGF4YQ0KDQpgYGB7cn0NCnBoeWx1bV9kYXRhIDwtIGFnZ3JlZ2F0ZV90YXhhKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhvbm9taWNfbGV2ZWwgPSAiUGh5bHVtIikNCg0KY29sb25fcGh5bHVtX3RhYiA8LSBwaHlsdW1fZGF0YVtbMV1dDQpjb2xvbl9waHlsdW1fdGF4YV90YWIgPC0gcGh5bHVtX2RhdGFbWzJdXQ0KDQpgYGANCg0KIyMjIyMgclBTQyB2cyBub24tclBTQw0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KKipsaW5EQSoqDQoNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmxpbmRhX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9waHlsdW1fdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3BoeWx1bV90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9ImxpbkRBIikNCg0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBsaW5kYV9kYXRhW1sxXV0NCmZpbHRfY29sb25fdW5pX3RheGEgPC0gbGluZGFfZGF0YVtbMl1dDQpmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSA8LSBsaW5kYV9kYXRhW1szXV0NCg0KIyBmaXQgdGhlIG1vZGVsDQpsaW5kYS5vYmogPC0gbGluZGEoZmlsdF9jb2xvbl91bmlfZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsIA0KICAgICAgICAgICAgICAgICAgIGZvcm11bGEgPSAnfiBHcm91cCAqIENvdW50cnkgKyAoMXxQYXRpZW50KScpDQoNCmxpbmRhLm91dHB1dCA8LSBsaW5kYS5vYmokb3V0cHV0DQpsaW5kYS5vdXRwdXQgPC0gbGluZGFfcmVuYW1pbmcobGluZGEub3V0cHV0LCBncm91cCkNCg0KZ3JvdXAxIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0pDQpncm91cDIgPC0gcGFzdGUwKGdyb3VwWzFdLCAiICwgIixncm91cFsyXSwgIiAtIENaIHZzIE5PIikgDQpncm91cDMgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSwgIjpDb3VudHJ5Tk8iKQ0KDQpmb3IgKGdycCBpbiBjKGdyb3VwMSxncm91cDIsZ3JvdXAzKSl7DQogIHJhd19saW5kYV9yZXN1bHRzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIHJhd2xpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV90YXhhKQ0KICANCiAgbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICBsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfdGF4YSkNCn0NCg0KYGBgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9NSwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KIyB2b2xjYW5vIHBsb3QNCnZvbGNhbm9fMSA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArDQogICAgICAgICAgICAgIGdndGl0bGUocGFzdGUoZ3JvdXAsY29sbGFwc2U9IiB2cyAiKSkNCg0Kdm9sY2Fub18yICA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfY29sb25fdW5pX3RheGEpICsgDQogICAgICAgICAgICAgIGdndGl0bGUoIkNvdW50cnkgZWZmZWN0IikNCg0Kdm9sY2Fub18zIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgICBnZ3RpdGxlKCJJbnRlcmFjdGlvbiIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm9fMSx2b2xjYW5vXzIsdm9sY2Fub18zLCBuY29sPTMpDQoNCiMgc2VlIHRoZSBwbG90DQp2b2xjYW5vDQpgYGANCg0KKipNYUFzTGluMioqDQoNCmBgYHtyLCBlY2hvPUZBTFNFLHJlc3VsdHM9J2hpZGUnLG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRX0NCmZpdF9kYXRhID0gTWFhc2xpbjIoDQogICAgaW5wdXRfZGF0YSA9IGZpbHRfY29sb25fdW5pX2RhdGEsIA0KICAgIGlucHV0X21ldGFkYXRhID0gZmlsdF9jb2xvbl91bmlfbWV0YWRhdGEsIG1pbl9hYnVuZGFuY2UgPSAwLA0KICAgIG1pbl9wcmV2YWxlbmNlID0gMCxtaW5fdmFyaWFuY2UgPSAwLA0KICAgIG91dHB1dCA9IGZpbGUucGF0aChwYXRoX21hYXNsaW4sZ3JvdXAxKSwgbWF4X3NpZ25pZmljYW5jZSA9IDAuMDUsDQogICAgZml4ZWRfZWZmZWN0cyA9IGMoJ0dyb3VwJywgJ0NvdW50cnknKSxyYW5kb21fZWZmZWN0cyA9ICJQYXRpZW50IiwNCiAgICBjb3JyZWN0aW9uID0gIkJIIikNCg0KYGBgDQoNClZvbGNhbm8gcGxvdA0KDQpgYGB7cn0NCnZvbGNhbm8xIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfY29sb25fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKHBhc3RlKGdyb3VwWzFdLCAidnMiLCBncm91cFsyXSkpDQoNCnZvbGNhbm8yIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfY29sb25fdW5pX3RheGEsdmFyaWFibGU9IkNvdW50cnkiKSArDQogICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm8gPC0gZ2dhcnJhbmdlKHZvbGNhbm8xLHZvbGNhbm8yLCBuY29sPTIpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQp2b2xjYW5vDQoNCmBgYA0KDQoqKkdyb3VwIC0gSW50ZXJzZWN0aW9uKioNCg0KYGBge3J9DQppbnRlcnNlY3Rpb25fcmVzdWx0cyA8LSBncm91cF9pbnRlcnNlY3Rpb24oZ3JvdXAsIGxpc3RfaW50ZXJzZWN0aW9ucywgbGlzdF92ZW5ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMV1dDQpsaXN0X3Zlbm5zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1syXV0NCnZlbm4gPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzNdXQ0KDQojIHNob3cgdGhlIHJlc3VsdHMNCnZlbm4NCmBgYA0KDQoqKkNvdW50cnkgLSBVbmlvbioqDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KbGlzdF9jb3VudHJ5X3VuaW9uIDwtIGNvdW50cnlfdW5pb24oZ3JvdXAsbGluZGEub3V0cHV0LCBmaXRfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCioqSW50ZXJhY3Rpb24gZWZmZWN0KioNCg0KYGBge3J9DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50IDwtIGNvdW50cnlfaW50ZXJhY3Rpb24oZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZGEub3V0cHV0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KIyBzZWUgdGhlIHJlc3VsdA0KIyMgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gZWZmZWN0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1sxXV0NCg0KIyMgcmVzdWx0cyBmb3IgY3plY2ggY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1syXV0NCg0KIyMgcmVzdWx0cyBmb3Igbm9yd2VnaWFuIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbM11dDQpgYGANCg0KUmVtb3ZpbmcgcHJvYmxlbWF0aWMgdGF4YQ0KDQpgYGB7cn0NCmxpc3RfaW50ZXJzZWN0aW9ucyA8LSByZW1vdmluZ19pbnRlcmFjdGlvbl9wcm9ibGVtcyhncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KQmFzaWMgc3RhdGlzdGljcw0KDQpgYGB7cn0NCnVuaV9kZiA8LSAgbWVyZ2UoYmFzaWNfdW5pdmFyaWF0ZV9zdGF0aXN0aWNzKGxpbmRhX2RhdGEsZ3JvdXApLA0KICAgICAgICAgICAgICAgICByYXdfbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncm91cDFdXSwNCiAgICAgICAgICAgICAgICAgYnk9IlNlcUlEIixhbGw9VFJVRSkNCg0KdW5pX2RmW1siZmluYWxfc2lnIl1dIDwtIHVuaV9kZiRTZXFJRCAlaW4lIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCxjb21wYXJpc29uX25hbWUpXV1bWyJTZXFJRCJdXQ0KdW5pX3N0YXRpc3RpY3NbW3NlZ21lbnRdXVtbcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dIDwtIHVuaV9kZg0KDQojIGZvciBjb21wYXJpc29uDQpuZXdfbmFtZSA8LSBwYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpDQphZGRXb3Jrc2hlZXQoc3VwcGxlbWVudHNfd2IsIHNoZWV0TmFtZSA9IG5ld19uYW1lKQ0Kd3JpdGVEYXRhKHN1cHBsZW1lbnRzX3diLCBzaGVldCA9IG5ld19uYW1lLCB1bmlfZGYsIHJvd05hbWVzPUZBTFNFKQ0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgaGVhbHRoeQ0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoImhlYWx0aHkiLCJyUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQoqKmxpbkRBKioNCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KbGluZGFfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX3BoeWx1bV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fcGh5bHVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9jb2xvbl91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfY29sb25fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2NvbG9uX3VuaV9kYXRhLCANCiAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwgDQogICAgICAgICAgICAgICAgICAgZm9ybXVsYSA9ICd+IEdyb3VwICogQ291bnRyeSArICgxfFBhdGllbnQpJykNCg0KbGluZGEub3V0cHV0IDwtIGxpbmRhLm9iaiRvdXRwdXQNCmxpbmRhLm91dHB1dCA8LSBsaW5kYV9yZW5hbWluZyhsaW5kYS5vdXRwdXQsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCmdyb3VwMSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIiwiR3JvdXAiLGdyb3VwWzJdKQ0KZ3JvdXAyIDwtIHBhc3RlMChncm91cFsxXSwgIiAsICIsZ3JvdXBbMl0sICIgLSBDWiB2cyBOTyIpIA0KZ3JvdXAzIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0sICI6Q291bnRyeU5PIikNCg0KZm9yIChncnAgaW4gYyhncm91cDEsZ3JvdXAyLGdyb3VwMykpew0KICByYXdfbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICByYXdsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfdGF4YSkNCiAgDQogIGxpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JwXV0gPC0gDQogICAgbGluZGEuZGYobGluZGEub3V0cHV0LA0KICAgICAgICAgICAgIGdycCwNCiAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX3RheGEpDQp9DQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQojIHZvbGNhbm8gcGxvdA0Kdm9sY2Fub18xIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfY29sb25fdW5pX3RheGEpICsNCiAgICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZShncm91cCxjb2xsYXBzZT0iIHZzICIpKQ0KDQp2b2xjYW5vXzIgIDwtIHZvbGNhbm9fcGxvdF9saW5kYShsaW5kYS5vdXRwdXQsIGdyb3VwMiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9jb2xvbl91bmlfdGF4YSkgKyANCiAgICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKQ0KDQp2b2xjYW5vXzMgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4YV90YWJsZSA9IGZpbHRfY29sb25fdW5pX3RheGEpICsgDQogICAgICAgICAgICAgIGdndGl0bGUoIkludGVyYWN0aW9uIikNCg0Kdm9sY2FubyA8LSBnZ2FycmFuZ2Uodm9sY2Fub18xLHZvbGNhbm9fMix2b2xjYW5vXzMsIG5jb2w9MykNCg0KIyBzZWUgdGhlIHBsb3QNCnZvbGNhbm8NCmBgYA0KDQoqKk1hQXNMaW4yKioNCg0KYGBge3IsIGVjaG89RkFMU0UscmVzdWx0cz0naGlkZScsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KZml0X2RhdGEgPSBNYWFzbGluMigNCiAgICBpbnB1dF9kYXRhID0gZmlsdF9jb2xvbl91bmlfZGF0YSwgDQogICAgaW5wdXRfbWV0YWRhdGEgPSBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwgbWluX2FidW5kYW5jZSA9IDAsDQogICAgbWluX3ByZXZhbGVuY2UgPSAwLG1pbl92YXJpYW5jZSA9IDAsDQogICAgb3V0cHV0ID0gZmlsZS5wYXRoKHBhdGhfbWFhc2xpbixncm91cDEpLCBtYXhfc2lnbmlmaWNhbmNlID0gMC4wNSwNCiAgICBmaXhlZF9lZmZlY3RzID0gYygnR3JvdXAnLCAnQ291bnRyeScpLHJhbmRvbV9lZmZlY3RzID0gIlBhdGllbnQiLA0KICAgIGNvcnJlY3Rpb24gPSAiQkgiKQ0KDQpgYGANCg0KYGBge3J9DQp2b2xjYW5vMSA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgZ2d0aXRsZShwYXN0ZShncm91cFsxXSwgInZzIiwgZ3JvdXBbMl0pKQ0KDQp2b2xjYW5vMiA8LSB2b2xjYW5vX3Bsb3RfbWFhc2xpbihmaXRfZGF0YSxmaWx0X2NvbG9uX3VuaV90YXhhLHZhcmlhYmxlPSJDb3VudHJ5IikgKw0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vMSx2b2xjYW5vMiwgbmNvbD0yKQ0KDQojIHNlZSB0aGUgcmVzdWx0cw0Kdm9sY2Fubw0KYGBgDQoNCioqR3JvdXAgLSBJbnRlcnNlY3Rpb24qKg0KDQpgYGB7cn0NCmludGVyc2VjdGlvbl9yZXN1bHRzIDwtIGdyb3VwX2ludGVyc2VjdGlvbihncm91cCwgbGlzdF9pbnRlcnNlY3Rpb25zLCBsaXN0X3Zlbm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCg0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1sxXV0NCmxpc3RfdmVubnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzJdXQ0KdmVubiA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbM11dDQoNCiMgc2hvdyB0aGUgcmVzdWx0cw0KdmVubg0KYGBgDQoNCioqQ291bnRyeSAtIFVuaW9uKioNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpsaXN0X2NvdW50cnlfdW5pb24gPC0gY291bnRyeV91bmlvbihncm91cCxsaW5kYS5vdXRwdXQsIGZpdF9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KKipJbnRlcmFjdGlvbiBlZmZlY3QqKg0KDQpgYGB7cn0NCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQgPC0gY291bnRyeV9pbnRlcmFjdGlvbihncm91cCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5kYS5vdXRwdXQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJzZWN0aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQ9c2VnbWVudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQojIHNlZSB0aGUgcmVzdWx0DQojIyBzaWduaWZpY2FudCBpbnRlcmFjdGlvbiBlZmZlY3QNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzFdXQ0KDQojIyByZXN1bHRzIGZvciBjemVjaCBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzJdXQ0KDQojIyByZXN1bHRzIGZvciBub3J3ZWdpYW4gY29ob3J0DQpsaXN0X2ludGVyYWN0aW9uX3NpZ25pZmljYW50W1szXV0NCmBgYA0KDQpSZW1vdmluZyBwcm9ibGVtYXRpYyB0YXhhDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcnNlY3Rpb25zIDwtIHJlbW92aW5nX2ludGVyYWN0aW9uX3Byb2JsZW1zKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQpgYGANCg0KKipCYXNpYyBzdGF0aXN0aWNzKioNCg0KYGBge3J9DQp1bmlfZGYgPC0gIG1lcmdlKGJhc2ljX3VuaXZhcmlhdGVfc3RhdGlzdGljcyhsaW5kYV9kYXRhLGdyb3VwKSwNCiAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHNbW3NlZ21lbnRdXVtbZ3JvdXAxXV0sDQogICAgICAgICAgICAgICAgIGJ5PSJTZXFJRCIsYWxsPVRSVUUpDQoNCnVuaV9kZltbImZpbmFsX3NpZyJdXSA8LSB1bmlfZGYkU2VxSUQgJWluJSBsaXN0X2ludGVyc2VjdGlvbnNbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwsY29tcGFyaXNvbl9uYW1lKV1dW1siU2VxSUQiXV0NCnVuaV9zdGF0aXN0aWNzW1tzZWdtZW50XV1bW3Bhc3RlKGxldmVsLGNvbXBhcmlzb25fbmFtZSldXSA8LSB1bmlfZGYNCg0KIyBmb3IgY29tcGFyaXNvbg0KbmV3X25hbWUgPC0gcGFzdGUobGV2ZWwsY29tcGFyaXNvbl9uYW1lKQ0KYWRkV29ya3NoZWV0KHN1cHBsZW1lbnRzX3diLCBzaGVldE5hbWUgPSBuZXdfbmFtZSkNCndyaXRlRGF0YShzdXBwbGVtZW50c193Yiwgc2hlZXQgPSBuZXdfbmFtZSwgdW5pX2RmLCByb3dOYW1lcz1GQUxTRSkNCmBgYA0KDQojIyMjIyBub24tclBTQyB2cyBoZWFsdGh5DQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiaGVhbHRoeSIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQoqKmxpbkRBKioNCg0KYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD01LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KbGluZGFfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX3BoeWx1bV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fcGh5bHVtX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibGluREEiKQ0KDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGxpbmRhX2RhdGFbWzFdXQ0KZmlsdF9jb2xvbl91bmlfdGF4YSA8LSBsaW5kYV9kYXRhW1syXV0NCmZpbHRfY29sb25fdW5pX21ldGFkYXRhIDwtIGxpbmRhX2RhdGFbWzNdXQ0KDQojIGZpdCB0aGUgbW9kZWwNCmxpbmRhLm9iaiA8LSBsaW5kYShmaWx0X2NvbG9uX3VuaV9kYXRhLCANCiAgICAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICBmb3JtdWxhID0gJ34gR3JvdXAgKiBDb3VudHJ5ICsgKDF8UGF0aWVudCknKQ0KDQpsaW5kYS5vdXRwdXQgPC0gbGluZGEub2JqJG91dHB1dA0KbGluZGEub3V0cHV0IDwtIGxpbmRhX3JlbmFtaW5nKGxpbmRhLm91dHB1dCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KZ3JvdXAxIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLCJHcm91cCIsZ3JvdXBbMl0pDQpncm91cDIgPC0gcGFzdGUwKGdyb3VwWzFdLCAiICwgIixncm91cFsyXSwgIiAtIENaIHZzIE5PIikgDQpncm91cDMgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsIkdyb3VwIixncm91cFsyXSwgIjpDb3VudHJ5Tk8iKQ0KDQpmb3IgKGdycCBpbiBjKGdyb3VwMSxncm91cDIsZ3JvdXAzKSl7DQogIHJhd19saW5kYV9yZXN1bHRzW1tzZWdtZW50XV1bW2dycF1dIDwtIA0KICAgIHJhd2xpbmRhLmRmKGxpbmRhLm91dHB1dCwNCiAgICAgICAgICAgICAgICBncnAsDQogICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICBmaWx0X2NvbG9uX3VuaV90YXhhKQ0KICANCiAgbGluZGFfcmVzdWx0c1tbc2VnbWVudF1dW1tncnBdXSA8LSANCiAgICBsaW5kYS5kZihsaW5kYS5vdXRwdXQsDQogICAgICAgICAgICAgZ3JwLA0KICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfdGF4YSkNCn0NCmBgYA0KDQpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCiMgdm9sY2FubyBwbG90DQp2b2xjYW5vXzEgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9jb2xvbl91bmlfdGF4YSkgKw0KICAgICAgICAgICAgICBnZ3RpdGxlKHBhc3RlKGdyb3VwLGNvbGxhcHNlPSIgdnMgIikpDQoNCnZvbGNhbm9fMiAgPC0gdm9sY2Fub19wbG90X2xpbmRhKGxpbmRhLm91dHB1dCwgZ3JvdXAyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheGFfdGFibGUgPSBmaWx0X2NvbG9uX3VuaV90YXhhKSArIA0KICAgICAgICAgICAgICBnZ3RpdGxlKCJDb3VudHJ5IGVmZmVjdCIpDQoNCnZvbGNhbm9fMyA8LSB2b2xjYW5vX3Bsb3RfbGluZGEobGluZGEub3V0cHV0LCBncm91cDMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhhX3RhYmxlID0gZmlsdF9jb2xvbl91bmlfdGF4YSkgKyANCiAgICAgICAgICAgICAgZ2d0aXRsZSgiSW50ZXJhY3Rpb24iKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vXzEsdm9sY2Fub18yLHZvbGNhbm9fMywgbmNvbD0zKQ0KDQojIHNlZSB0aGUgcGxvdA0Kdm9sY2Fubw0KYGBgDQoNCioqTWFBc0xpbjIqKg0KDQpgYGB7ciwgZWNobz1GQUxTRSxyZXN1bHRzPSdoaWRlJyxtZXNzYWdlPUZBTFNFLHdhcm5pbmc9RkFMU0V9DQpmaXRfZGF0YSA9IE1hYXNsaW4yKA0KICAgIGlucHV0X2RhdGEgPSBmaWx0X2NvbG9uX3VuaV9kYXRhLCANCiAgICBpbnB1dF9tZXRhZGF0YSA9IGZpbHRfY29sb25fdW5pX21ldGFkYXRhLCBtaW5fYWJ1bmRhbmNlID0gMCwNCiAgICBtaW5fcHJldmFsZW5jZSA9IDAsbWluX3ZhcmlhbmNlID0gMCwNCiAgICBvdXRwdXQgPSBmaWxlLnBhdGgocGF0aF9tYWFzbGluLGdyb3VwMSksIG1heF9zaWduaWZpY2FuY2UgPSAwLjA1LA0KICAgIGZpeGVkX2VmZmVjdHMgPSBjKCdHcm91cCcsICdDb3VudHJ5JykscmFuZG9tX2VmZmVjdHMgPSAiUGF0aWVudCIsDQogICAgY29ycmVjdGlvbiA9ICJCSCIpDQoNCmBgYA0KDQpgYGB7cn0NCnZvbGNhbm8xIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfY29sb25fdW5pX3RheGEpICsgDQogICAgICAgICAgICBnZ3RpdGxlKHBhc3RlKGdyb3VwWzFdLCAidnMiLCBncm91cFsyXSkpDQoNCnZvbGNhbm8yIDwtIHZvbGNhbm9fcGxvdF9tYWFzbGluKGZpdF9kYXRhLGZpbHRfY29sb25fdW5pX3RheGEsdmFyaWFibGU9IkNvdW50cnkiKSArIA0KICAgICAgICAgICAgZ2d0aXRsZSgiQ291bnRyeSBlZmZlY3QiKQ0KDQp2b2xjYW5vIDwtIGdnYXJyYW5nZSh2b2xjYW5vMSx2b2xjYW5vMiwgbmNvbD0yKQ0Kdm9sY2Fubw0KYGBgDQoNCioqR3JvdXAgLSBJbnRlcnNlY3Rpb24qKg0KDQpgYGB7cn0NCmludGVyc2VjdGlvbl9yZXN1bHRzIDwtIGdyb3VwX2ludGVyc2VjdGlvbihncm91cCwgbGlzdF9pbnRlcnNlY3Rpb25zLCBsaXN0X3Zlbm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X2xpbmRhX3Jlc3VsdHMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZ21lbnQgPSBzZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KDQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gaW50ZXJzZWN0aW9uX3Jlc3VsdHNbWzFdXQ0KbGlzdF92ZW5ucyA8LSBpbnRlcnNlY3Rpb25fcmVzdWx0c1tbMl1dDQp2ZW5uIDwtIGludGVyc2VjdGlvbl9yZXN1bHRzW1szXV0NCg0KIyBzaG93IHRoZSByZXN1bHRzDQp2ZW5uDQpgYGANCg0KKipDb3VudHJ5IC0gVW5pb24qKg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmxpc3RfY291bnRyeV91bmlvbiA8LSBjb3VudHJ5X3VuaW9uKGdyb3VwLGxpbmRhLm91dHB1dCwgZml0X2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWdtZW50PXNlZ21lbnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbD1sZXZlbCkNCmBgYA0KDQoqKkludGVyYWN0aW9uIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCA8LSBjb3VudHJ5X2ludGVyYWN0aW9uKGdyb3VwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmRhLm91dHB1dCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRfY29sb25fdW5pX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWw9bGV2ZWwpDQoNCiMgc2VlIHRoZSByZXN1bHQNCiMjIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGVmZmVjdA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMV1dDQoNCiMjIHJlc3VsdHMgZm9yIGN6ZWNoIGNvaG9ydA0KbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudFtbMl1dDQoNCiMjIHJlc3VsdHMgZm9yIG5vcndlZ2lhbiBjb2hvcnQNCmxpc3RfaW50ZXJhY3Rpb25fc2lnbmlmaWNhbnRbWzNdXQ0KYGBgDQoNClJlbW92aW5nIHByb2JsZW1hdGljIHRheGENCg0KYGBge3J9DQpsaXN0X2ludGVyc2VjdGlvbnMgPC0gcmVtb3ZpbmdfaW50ZXJhY3Rpb25fcHJvYmxlbXMoZ3JvdXAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdF9pbnRlcmFjdGlvbl9zaWduaWZpY2FudCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2ludGVyc2VjdGlvbnMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VnbWVudD1zZWdtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsPWxldmVsKQ0KYGBgDQoNCiBCYXNpYyBzdGF0aXN0aWNzDQoNCmBgYHtyfQ0KdW5pX2RmIDwtICBtZXJnZShiYXNpY191bml2YXJpYXRlX3N0YXRpc3RpY3MobGluZGFfZGF0YSxncm91cCksDQogICAgICAgICAgICAgICAgIHJhd19saW5kYV9yZXN1bHRzW1tzZWdtZW50XV1bW2dyb3VwMV1dLA0KICAgICAgICAgICAgICAgICBieT0iU2VxSUQiLGFsbD1UUlVFKQ0KDQp1bmlfZGZbWyJmaW5hbF9zaWciXV0gPC0gdW5pX2RmJFNlcUlEICVpbiUgbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLGNvbXBhcmlzb25fbmFtZSldXVtbIlNlcUlEIl1dDQp1bmlfc3RhdGlzdGljc1tbc2VnbWVudF1dW1twYXN0ZShsZXZlbCxjb21wYXJpc29uX25hbWUpXV0gPC0gdW5pX2RmDQoNCiMgZm9yIGNvbXBhcmlzb24NCm5ld19uYW1lIDwtIHBhc3RlKGxldmVsLGNvbXBhcmlzb25fbmFtZSkNCmFkZFdvcmtzaGVldChzdXBwbGVtZW50c193Yiwgc2hlZXROYW1lID0gbmV3X25hbWUpDQp3cml0ZURhdGEoc3VwcGxlbWVudHNfd2IsIHNoZWV0ID0gbmV3X25hbWUsIHVuaV9kZiwgcm93TmFtZXM9RkFMU0UpDQpgYGANCg0KIyMjIyMgVmlzdWFsaXphdGlvbg0KDQpIZWF0bWFwIHZpc3VhbGl6aW5nIHRoZSBsaW5EQSdzIGxvZ0ZvbGRDaGFuZ2UgZm9yIHRheGEgd2l0aCBwIFw8IDAuMS4NCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xNywgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KbGlzdF9oZWF0bWFwIDwtIGxpc3RfaW50ZXJzZWN0aW9uc1tncmVwKHBhc3RlKHNlZ21lbnQsbGV2ZWwpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzKGxpc3RfaW50ZXJzZWN0aW9ucyksdmFsdWU9VFJVRSldDQoNCnBfaGVhdG1hcF9saW5kYSA8LSBoZWF0bWFwX2xpbmRhKGxpc3RfaGVhdG1hcCxjb2xvbl90YXhhX3RhYikNCnBfaGVhdG1hcF9saW5kYQ0KYGBgDQoNCioqRG90IGhlYXRtYXAqKg0KDQpgYGB7ciwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9MjUsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCmRvdGhlYXRtYXBfbGluZGEgPC0gZG90X2hlYXRtYXBfbGluZGEobGlzdF9oZWF0bWFwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmlfc3RhdGlzdGljcyRjb2xvbltncmVwbChsZXZlbCxuYW1lcyh1bmlfc3RhdGlzdGljcyRjb2xvbikpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIpDQpkb3RoZWF0bWFwX2xpbmRhDQpgYGANCg0KIyMjIyMgclBTQyBlZmZlY3QNCg0KKipwcmVfTFR4IHZzIEhlYWx0aHkgYW5kIFBvc3RfTFR4IHZzIEhlYWx0aHkgaW50ZXJzZWN0aW9uKioNCg0KDQpgYGB7cn0NCkEgPC0gbGlzdF9pbnRlcnNlY3Rpb25zW1twYXN0ZShzZWdtZW50LGxldmVsLCJoZWFsdGh5IHZzIHJQU0MiKV1dDQpCIDwtIGxpc3RfaW50ZXJzZWN0aW9uc1tbcGFzdGUoc2VnbWVudCxsZXZlbCwiaGVhbHRoeSB2cyBub24tclBTQyIpXV0NCmRmIDwtIEFbIShBJFNlcUlEICVpbiUgQiRTZXFJRCksXQ0KDQpycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSA8LSBkZg0KICANCiMgc2VlIHRoZSByZXN1bHRzDQpycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSANCmBgYA0KDQojIyMjIFNhdmluZyByZXN1bHRzDQoNCmBgYHtyfQ0KIyBBTEwgREFUQQ0Kc2F2ZVdvcmtib29rKHN1cHBsZW1lbnRzX3diLGZpbGUucGF0aChwYXRoLHBhc3RlMCgic3VwcGxlbWVudHNfdW5pX2FuYWx5c2lzX3diXyIsc2VnbWVudCwiLnhsc3giKSksb3ZlcndyaXRlID0gVFJVRSkNCg0KIyBQU0MgZWZmZWN0DQp3cml0ZS54bHN4KHJwc2NfZWZmZWN0LA0KICAgICAgICAgIGZpbGUucGF0aChwYXRoLHBhc3RlMCgic3VwcGxlbWVudHNfcnBzY19lZmZlY3RfIixzZWdtZW50LCIueGxzeCIpKSkNCg0KIyBTSUdOSUZJQ0FOVCB0YXhhDQp3cml0ZS54bHN4KGxpc3RfaW50ZXJzZWN0aW9uc1tncmVwbChzZWdtZW50LG5hbWVzKGxpc3RfaW50ZXJzZWN0aW9ucykpXSAlPiUNCiAgICAgICAgICAgIGBuYW1lczwtYChnc3ViKHNlZ21lbnQsICIiLCBuYW1lcygNCiAgICAgICAgICAgICAgbGlzdF9pbnRlcnNlY3Rpb25zW2dyZXBsKHNlZ21lbnQsbmFtZXMobGlzdF9pbnRlcnNlY3Rpb25zKSldKSkpLA0KICAgICAgICAgICBmaWxlLnBhdGgocGF0aCxwYXN0ZTAoInN1cHBsZW1lbnRzX3NpZ25pZmljYW50X3RheGFfIixzZWdtZW50LCIueGxzeCIpKSkNCmBgYA0KDQojIyBNYWNoaW5lIGxlYXJuaW5nDQoNCmBgYHtyfQ0KcGF0aCA9ICIuLi9yZXN1bHRzL1EyL21vZGVscyINCmBgYA0KDQojIyMgRWxhc3RpY05ldA0KDQpgYGB7cn0NCm1vZGVsPSJlbmV0Ig0KYGBgDQoNCiMjIyMgQVNWIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9IkFTViINCmBgYA0KDQojIyMjIyByUFNDIHZzIG5vbi1yUFNDDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DDQpyb2NfYyA8LSByb2NfY3VydmUoZW5ldF9tb2RlbCwgZ3JvdXApDQoNCm1vZGVsc19zdW1tW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQptb2RlbHNfY21bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGNvbmZfbWF0cmljZXMkb3JpZ2luYWwNCnJvY19jc1tbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KYmV0YXNbW21vZGVsX25hbWVdXSA8LSBhcy5tYXRyaXgoZW5ldF9tb2RlbCRiZXRhcykNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQplbmV0X21vZGVsJGNvbmZfbWF0cmljZXMNCmVuZXRfbW9kZWwkcGxvdA0Kcm9jX2MNCmBgYA0KDQojIyMjIyByUFNDIHZzIGhlYWx0aHkNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfY2xyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQplbmV0X21vZGVsIDwtIGdsbW5ldF9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQptb2RlbHNfc3VtbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KbW9kZWxzX2NtW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzJG9yaWdpbmFsDQpyb2NfY3NbW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCmJldGFzW1ttb2RlbF9uYW1lXV0gPC0gYXMubWF0cml4KGVuZXRfbW9kZWwkYmV0YXMpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0KZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzDQplbmV0X21vZGVsJHBsb3QNCg0Kcm9jX2MNCmBgYA0KDQojIyMjIyBub24tclBTQyB2cyBoZWFsdGh5DQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DDQpyb2NfYyA8LSByb2NfY3VydmUoZW5ldF9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KbW9kZWxzX3N1bW1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCm1vZGVsc19jbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkY29uZl9tYXRyaWNlcyRvcmlnaW5hbA0Kcm9jX2NzW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQpiZXRhc1tbbW9kZWxfbmFtZV1dIDwtIGFzLm1hdHJpeChlbmV0X21vZGVsJGJldGFzKQ0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCmVuZXRfbW9kZWwkY29uZl9tYXRyaWNlcw0KZW5ldF9tb2RlbCRwbG90DQoNCnJvY19jDQpgYGANCg0KIyMjIyMgclBTQyBlZmZlY3QNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQptb2RlbHNfc3VtbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KbW9kZWxzX2NtW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzJG9yaWdpbmFsDQpyb2NfY3NbW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCmJldGFzW1ttb2RlbF9uYW1lXV0gPC0gYXMubWF0cml4KGVuZXRfbW9kZWwkYmV0YXMpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0KZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzDQplbmV0X21vZGVsJHBsb3QNCg0Kcm9jX2MNCmBgYA0KDQojIyMjIEdlbnVzIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9ImdlbnVzIg0KYGBgDQoNCkFnZ3JlZ2F0ZSB0YXhhDQoNCmBgYHtyfQ0KZ2VudXNfZGF0YSA8LSBhZ2dyZWdhdGVfdGF4YShjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4b25vbWljX2xldmVsID0gbGV2ZWwpDQoNCmNvbG9uX2dlbnVzX3RhYiA8LSBnZW51c19kYXRhW1sxXV0NCmNvbG9uX2dlbnVzX3RheGFfdGFiIDwtIGdlbnVzX2RhdGFbWzJdXQ0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgbm9uLXJQU0MNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQplbmV0X21vZGVsIDwtIGdsbW5ldF9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQw0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCm1vZGVsc19zdW1tW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQptb2RlbHNfY21bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGNvbmZfbWF0cmljZXMkb3JpZ2luYWwNCnJvY19jc1tbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KYmV0YXNbW21vZGVsX25hbWVdXSA8LSBhcy5tYXRyaXgoZW5ldF9tb2RlbCRiZXRhcykNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQplbmV0X21vZGVsJGNvbmZfbWF0cmljZXMNCmVuZXRfbW9kZWwkcGxvdA0KDQpyb2NfYw0KYGBgDQoNCiMjIyMjIHJQU0MgdnMgaGVhbHRoeQ0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQptb2RlbHNfc3VtbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KbW9kZWxzX2NtW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzJG9yaWdpbmFsDQpyb2NfY3NbW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCmJldGFzW1ttb2RlbF9uYW1lXV0gPC0gYXMubWF0cml4KGVuZXRfbW9kZWwkYmV0YXMpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0KZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzDQplbmV0X21vZGVsJHBsb3QNCg0Kcm9jX2MNCmBgYA0KDQojIyMjIyByUFNDIHZzIGhlYWx0aHkNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQplbmV0X21vZGVsIDwtIGdsbW5ldF9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DDQpyb2NfYyA8LSByb2NfY3VydmUoZW5ldF9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KbW9kZWxzX3N1bW1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCm1vZGVsc19jbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkY29uZl9tYXRyaWNlcyRvcmlnaW5hbA0Kcm9jX2NzW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQpiZXRhc1tbbW9kZWxfbmFtZV1dIDwtIGFzLm1hdHJpeChlbmV0X21vZGVsJGJldGFzKQ0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCmVuZXRfbW9kZWwkY29uZl9tYXRyaWNlcw0KZW5ldF9tb2RlbCRwbG90DQpyb2NfYw0KYGBgDQoNCiMjIyMjIHJQU0MgZWZmZWN0DQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQptb2RlbHNfc3VtbVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KbW9kZWxzX2NtW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzJG9yaWdpbmFsDQpyb2NfY3NbW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCmJldGFzW1ttb2RlbF9uYW1lXV0gPC0gYXMubWF0cml4KGVuZXRfbW9kZWwkYmV0YXMpDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0KZW5ldF9tb2RlbCRjb25mX21hdHJpY2VzDQplbmV0X21vZGVsJHBsb3QNCg0Kcm9jX2MNCmBgYA0KDQojIyMjIFNhdmluZyByZXN1bHRzDQoNCmBgYHtyfQ0KbW9kZWxzX3N1bW1fZGZfY29sb24gPC0gZG8uY2FsbChyYmluZCwgDQogIG1vZGVsc19zdW1tW2dyZXAoc2VnbWVudCxuYW1lcyhtb2RlbHNfc3VtbSksdmFsdWUgPSBUUlVFKV0pDQoNCndyaXRlLmNzdihtb2RlbHNfc3VtbV9kZl9jb2xvbixmaWxlLnBhdGgocGF0aCxwYXN0ZTAoImVsYXN0aWNfbmV0XyIsc2VnbWVudCwiLmNzdiIpKSkNCmBgYA0KDQojIyMgU3VwcGxlbWVudGFyeSBtb2RlbHMNCg0KIyMjIyBDTFItdHJhbnNmb3JtZWQgZGF0YQ0KDQojIyMjIyBrTk4NCg0KYGBge3J9DQptb2RlbD0ia25uIg0KYGBgDQoNCiMjIyMjIyBBU1YgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iQVNWIg0KYGBgDQoNCioqKnJQU0MgdnMgbm9uLXJQU0MqKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoa25uX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQprbm5fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyMgR2VudXMgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iZ2VudXMiDQpgYGANCg0KQWdncmVnYXRlIHRheGENCg0KYGBge3J9DQpnZW51c19kYXRhIDwtIGFnZ3JlZ2F0ZV90YXhhKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhvbm9taWNfbGV2ZWwgPSBsZXZlbCkNCg0KY29sb25fZ2VudXNfdGFiIDwtIGdlbnVzX2RhdGFbWzFdXQ0KY29sb25fZ2VudXNfdGF4YV90YWIgPC0gZ2VudXNfZGF0YVtbMl1dDQpgYGANCg0KKipyUFNDIHZzIG5vbi1yUFNDKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoa25uX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQprbm5fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoa25uX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQprbm5fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyBlZmZlY3QqKg0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfY2xyIikNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sia25uX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KIyMjIyMgUmFuZG9tIEZvcmVzdA0KDQpgYGB7cn0NCm1vZGVsPSJyZiINCmBgYA0KDQojIyMjIyMgQVNWIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9IkFTViINCmBgYA0KDQoqKipyUFNDIHZzIG5vbi1yUFNDKioqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUocmZfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUocmZfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCg0KIyMjIyMjIEdlbnVzIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9ImdlbnVzIg0KYGBgDQoNCkFnZ3JlZ2F0ZSB0YXhhDQoNCmBgYHtyfQ0KZ2VudXNfZGF0YSA8LSBhZ2dyZWdhdGVfdGF4YShjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4b25vbWljX2xldmVsID0gbGV2ZWwpDQoNCmNvbG9uX2dlbnVzX3RhYiA8LSBnZW51c19kYXRhW1sxXV0NCmNvbG9uX2dlbnVzX3RheGFfdGFiIDwtIGdlbnVzX2RhdGFbWzJdXQ0KYGBgDQoNCioqclBTQyB2cyBub24tclBTQyoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUocmZfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCnJmX21vZGVsIDwtIHJmX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUocmZfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpyZl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KIyMjIyMgR3JhZGllbnQgYm9vc3RpbmcNCg0KYGBge3J9DQptb2RlbD0iZ2IiDQpgYGANCg0KIyMjIyMjIEFTViBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJBU1YiDQpgYGANCg0KKioqclBTQyB2cyBub24tclBTQyoqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfY2xyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfY2xyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyBlZmZlY3QqKg0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCiMjIyMjIyBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpBZ2dyZWdhdGUgdGF4YQ0KDQpgYGB7cn0NCmdlbnVzX2RhdGEgPC0gYWdncmVnYXRlX3RheGEoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheG9ub21pY19sZXZlbCA9IGxldmVsKQ0KDQpjb2xvbl9nZW51c190YWIgPC0gZ2VudXNfZGF0YVtbMV1dDQpjb2xvbl9nZW51c190YXhhX3RhYiA8LSBnZW51c19kYXRhW1syXV0NCmBgYA0KDQoqKnJQU0MgdnMgbm9uLXJQU0MqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX2NsciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbCJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9jbHIiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWwiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIFJlbGF0aXZlIGFidW5kYW5jZXMNCg0KIyMjIyMgRWxhc3RpYyBuZXQNCg0KIyMjIyMjIEFTViBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJBU1YiDQpgYGANCg0KKioqclBTQyB2cyBub24tclBTQyoqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZW5ldF9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImVuZXRfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZW5ldF9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImVuZXRfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQplbmV0X21vZGVsIDwtIGdsbW5ldF9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyMgR2VudXMgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iZ2VudXMiDQpgYGANCg0KQWdncmVnYXRlIHRheGENCg0KYGBge3J9DQpnZW51c19kYXRhIDwtIGFnZ3JlZ2F0ZV90YXhhKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhvbm9taWNfbGV2ZWwgPSBsZXZlbCkNCg0KY29sb25fZ2VudXNfdGFiIDwtIGdlbnVzX2RhdGFbWzFdXQ0KY29sb25fZ2VudXNfdGF4YV90YWIgPC0gZ2VudXNfZGF0YVtbMl1dDQpgYGANCg0KKipyUFNDIHZzIG5vbi1yUFNDKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmVuZXRfbW9kZWwgPC0gZ2xtbmV0X2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZW5ldF9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImVuZXRfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQplbmV0X21vZGVsIDwtIGdsbW5ldF9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShlbmV0X21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImVuZXRfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBlbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZW5ldF9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZW5ldF9tb2RlbCA8LSBnbG1uZXRfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGVuZXRfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZW5ldF9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGVuZXRfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJlbmV0X21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZW5ldF9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQplbmV0X21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyBrTk4NCg0KIyMjIyMjIEFTViBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJBU1YiDQpgYGANCg0KKioqclBTQyB2cyBub24tclBTQyoqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sia25uX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipub24tclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJub24tclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQprbm5fbW9kZWwgPC0ga25uX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShrbm5fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sia25uX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sia25uX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0ga25uX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyMgR2VudXMgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iZ2VudXMiDQpgYGANCg0KQWdncmVnYXRlIHRheGENCg0KYGBge3J9DQpnZW51c19kYXRhIDwtIGFnZ3JlZ2F0ZV90YXhhKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXhvbm9taWNfbGV2ZWwgPSBsZXZlbCkNCg0KY29sb25fZ2VudXNfdGFiIDwtIGdlbnVzX2RhdGFbWzFdXQ0KY29sb25fZ2VudXNfdGF4YV90YWIgPC0gZ2VudXNfZGF0YVtbMl1dDQpgYGANCg0KKipyUFNDIHZzIG5vbi1yUFNDKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0Ka25uX21vZGVsIDwtIGtubl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoa25uX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImtubl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQprbm5fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyBlZmZlY3QqKg0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoInJQU0MgZWZmZWN0IixsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcF9wc2NfZWZmZWN0KGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX2dlbnVzX3RheGFfdGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnBzY19lZmZlY3RbW3Bhc3RlKHNlZ21lbnQsbGV2ZWwpXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2FnZT0ibWxfcmEiKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmtubl9tb2RlbCA8LSBrbm5fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGtubl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImtubl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGtubl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJrbm5fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBrbm5fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0Ka25uX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyBSYW5kb20gRm9yZXN0DQoNCiMjIyMjIyBBU1YgbGV2ZWwNCg0KYGBge3J9DQpsZXZlbD0iQVNWIg0KYGBgDQoNCioqKnJQU0MgdnMgbm9uLXJQU0MqKioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwibm9uLXJQU0MiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQpyZl9tb2RlbCA8LSByZl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsImhlYWx0aHkiKQ0KY29tcGFyaXNvbl9uYW1lIDwtIHBhc3RlMChncm91cFsxXSwgIiB2cyAiLGdyb3VwWzJdKQ0KYGBgDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZShjb21wYXJpc29uX25hbWUsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXAoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgdXNhZ2U9Im1sX3JhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQpyZl9tb2RlbCA8LSByZl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9yYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpyZl9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KIyMjIyMjIEdlbnVzIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9ImdlbnVzIg0KYGBgDQoNCkFnZ3JlZ2F0ZSB0YXhhDQoNCmBgYHtyfQ0KZ2VudXNfZGF0YSA8LSBhZ2dyZWdhdGVfdGF4YShjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl90YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGF4b25vbWljX2xldmVsID0gbGV2ZWwpDQoNCmNvbG9uX2dlbnVzX3RhYiA8LSBnZW51c19kYXRhW1sxXV0NCmNvbG9uX2dlbnVzX3RheGFfdGFiIDwtIGdlbnVzX2RhdGFbWzJdXQ0KYGBgDQoNCioqclBTQyB2cyBub24tclBTQyoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQpyZl9tb2RlbCA8LSByZl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKHJmX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbInJmX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gcmZfbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KDQojIHNlZSB0aGUgcmVzdWx0cw0KcmZfbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KcmZfbW9kZWwgPC0gcmZfYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShyZl9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJwc2NfZWZmZWN0W1twYXN0ZShzZWdtZW50LGxldmVsKV1dLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIikNCg0KIyBmaXQgdGhlIG1vZGVsDQpyZl9tb2RlbCA8LSByZl9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUocmZfbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1sicmZfbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSByZl9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJyZl9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIHJmX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCnJmX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQojIyMjIyBHcmFkaWVudCBib29zdGluZw0KDQojIyMjIyMgQVNWIGxldmVsDQoNCmBgYHtyfQ0KbGV2ZWw9IkFTViINCmBgYA0KDQoqKipyUFNDIHZzIG5vbi1yUFNDKioqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygiclBTQyIsIm5vbi1yUFNDIikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2Fzdl90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIHVzYWdlPSJtbF9yYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKm5vbi1yUFNDIHZzIGhlYWx0aHkqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoIm5vbi1yUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX3RheGFfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9uX21ldGFkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLCB1c2FnZT0ibWxfcmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGllbnQgPSBUUlVFKQ0KDQojIGZpdCB0aGUgbW9kZWwNCmdibV9tb2RlbCA8LSBnYm1fYmlub21pYWwoZmlsdF9jb2xvbl91bmlfZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbXBsZV9tZXRob2QgPSAiYXR5cGJvb3QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0Y29tZT0iR3JvdXAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE49MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0X3Zhcj0iUGF0aWVudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXVzZT1UUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZT1tb2RlbF9uYW1lLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiKQ0KDQojIFJPQyBjdXJ2ZQ0Kcm9jX2MgPC0gcm9jX2N1cnZlKGdibV9tb2RlbCwgZ3JvdXApDQoNCiMgc2F2ZSB0aGUgcmVzdWx0cw0Kc3VwcGxlbWVudHNfbW9kZWxzW1sibW9kZWxzX3N1bW0iXV1bWyJnYm1fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeQ0KDQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQojIHNlZSB0aGUgcmVzdWx0cw0KZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkgJT4lIHQoKQ0Kcm9jX2MNCmBgYA0KDQoqKnJQU0MgZWZmZWN0KioNCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKCJyUFNDIGVmZmVjdCIsbGV2ZWwsc2VnbWVudCkNCg0KIyBwcmVwYXJlIHRoZSBkYXRhDQpmaWx0X2NvbG9uX3VuaV9kYXRhIDwtIGJpbm9taWFsX3ByZXBfcHNjX2VmZmVjdChjb2xvbl9hc3ZfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCiMjIyMjIyBHZW51cyBsZXZlbA0KDQpgYGB7cn0NCmxldmVsPSJnZW51cyINCmBgYA0KDQpBZ2dyZWdhdGUgdGF4YQ0KDQpgYGB7cn0NCmdlbnVzX2RhdGEgPC0gYWdncmVnYXRlX3RheGEoY29sb25fYXN2X3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRheG9ub21pY19sZXZlbCA9IGxldmVsKQ0KDQpjb2xvbl9nZW51c190YWIgPC0gZ2VudXNfZGF0YVtbMV1dDQpjb2xvbl9nZW51c190YXhhX3RhYiA8LSBnZW51c19kYXRhW1syXV0NCmBgYA0KDQoqKnJQU0MgdnMgbm9uLXJQU0MqKg0KDQpgYGB7cn0NCmdyb3VwIDwtIGMoInJQU0MiLCJub24tclBTQyIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqclBTQyB2cyBoZWFsdGh5KioNCg0KYGBge3J9DQpncm91cCA8LSBjKCJyUFNDIiwiaGVhbHRoeSIpDQpjb21wYXJpc29uX25hbWUgPC0gcGFzdGUwKGdyb3VwWzFdLCAiIHZzICIsZ3JvdXBbMl0pDQpgYGANCg0KYGBge3J9DQptb2RlbF9uYW1lIDwtIHBhc3RlKGNvbXBhcmlzb25fbmFtZSxsZXZlbCxzZWdtZW50KQ0KDQojIHByZXBhcmUgdGhlIGRhdGENCmZpbHRfY29sb25fdW5pX2RhdGEgPC0gYmlub21pYWxfcHJlcChjb2xvbl9nZW51c190YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aWVudCA9IFRSVUUpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3RfdmFyPSJQYXRpZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQoNCnN1cHBsZW1lbnRzX21vZGVsc1tbInJvY19jcyJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRrZm9sZF9yb2NvYmpzDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCioqbm9uLXJQU0MgdnMgaGVhbHRoeSoqDQoNCmBgYHtyfQ0KZ3JvdXAgPC0gYygibm9uLXJQU0MiLCJoZWFsdGh5IikNCmNvbXBhcmlzb25fbmFtZSA8LSBwYXN0ZTAoZ3JvdXBbMV0sICIgdnMgIixncm91cFsyXSkNCmBgYA0KDQpgYGB7cn0NCm1vZGVsX25hbWUgPC0gcGFzdGUoY29tcGFyaXNvbl9uYW1lLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwKGNvbG9uX2dlbnVzX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9nZW51c190YXhhX3RhYiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvbl9tZXRhZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNhZ2U9Im1sX3JhIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRpZW50ID0gVFJVRSkNCg0KIyBmaXQgdGhlIG1vZGVsDQpnYm1fbW9kZWwgPC0gZ2JtX2Jpbm9taWFsKGZpbHRfY29sb25fdW5pX2RhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1wbGVfbWV0aG9kID0gImF0eXBib290IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGNvbWU9Ikdyb3VwIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOPTEwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdF92YXI9IlBhdGllbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV1c2U9VFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGU9bW9kZWxfbmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIikNCg0KIyBST0MgY3VydmUNCnJvY19jIDwtIHJvY19jdXJ2ZShnYm1fbW9kZWwsIGdyb3VwKQ0KDQojIHNhdmUgdGhlIHJlc3VsdHMNCnN1cHBsZW1lbnRzX21vZGVsc1tbIm1vZGVsc19zdW1tIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJG1vZGVsX3N1bW1hcnkNCg0Kc3VwcGxlbWVudHNfbW9kZWxzW1sicm9jX2NzIl1dW1siZ2JtX21vZGVsX3JhIl1dW1ttb2RlbF9uYW1lXV0gPC0gZ2JtX21vZGVsJGtmb2xkX3JvY29ianMNCg0KIyBzZWUgdGhlIHJlc3VsdHMNCmdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5ICU+JSB0KCkNCnJvY19jDQpgYGANCg0KKipyUFNDIGVmZmVjdCoqDQoNCmBgYHtyfQ0KbW9kZWxfbmFtZSA8LSBwYXN0ZSgiclBTQyBlZmZlY3QiLGxldmVsLHNlZ21lbnQpDQoNCiMgcHJlcGFyZSB0aGUgZGF0YQ0KZmlsdF9jb2xvbl91bmlfZGF0YSA8LSBiaW5vbWlhbF9wcmVwX3BzY19lZmZlY3QoY29sb25fZ2VudXNfdGFiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fZ2VudXNfdGF4YV90YWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fbWV0YWRhdGEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBycHNjX2VmZmVjdFtbcGFzdGUoc2VnbWVudCxsZXZlbCldXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzYWdlPSJtbF9yYSIpDQoNCiMgZml0IHRoZSBtb2RlbA0KZ2JtX21vZGVsIDwtIGdibV9iaW5vbWlhbChmaWx0X2NvbG9uX3VuaV9kYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX21ldGhvZCA9ICJhdHlwYm9vdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRjb21lPSJHcm91cCIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTj0xMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldXNlPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlPW1vZGVsX25hbWUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIpDQoNCiMgUk9DIGN1cnZlDQpyb2NfYyA8LSByb2NfY3VydmUoZ2JtX21vZGVsLCBncm91cCkNCg0KIyBzYXZlIHRoZSByZXN1bHRzDQpzdXBwbGVtZW50c19tb2RlbHNbWyJtb2RlbHNfc3VtbSJdXVtbImdibV9tb2RlbF9yYSJdXVtbbW9kZWxfbmFtZV1dIDwtIGdibV9tb2RlbCRtb2RlbF9zdW1tYXJ5DQpzdXBwbGVtZW50c19tb2RlbHNbWyJyb2NfY3MiXV1bWyJnYm1fbW9kZWxfcmEiXV1bW21vZGVsX25hbWVdXSA8LSBnYm1fbW9kZWwka2ZvbGRfcm9jb2Jqcw0KDQoNCiMgc2VlIHRoZSByZXN1bHRzDQpnYm1fbW9kZWwkbW9kZWxfc3VtbWFyeSAlPiUgdCgpDQpyb2NfYw0KYGBgDQoNCiMjIyMgU2F2aW5nIHJlc3VsdHMNCg0KYGBge3J9DQptb2RlbHNfbGlzdCA8LSBsaXN0KCkNCg0KZm9yIChtb2RlbF9uYW1lIGluIG5hbWVzKHN1cHBsZW1lbnRzX21vZGVscyRtb2RlbHNfc3VtbSkpew0KICBkZiA8LSBkby5jYWxsKHJiaW5kLCBzdXBwbGVtZW50c19tb2RlbHMkbW9kZWxzX3N1bW1bW21vZGVsX25hbWVdXSkNCiAgbW9kZWxzX2xpc3RbW21vZGVsX25hbWVdXSA8LSBkZg0KfQ0KDQp3cml0ZS54bHN4KG1vZGVsc19saXN0LA0KICAgICAgICAgICBmaWxlPWZpbGUucGF0aChwYXRoLHBhc3RlMCgic3VwcGxlbWVudHNfbW9kZWxzXyIsc2VnbWVudCwiLnhsc3giKSksDQogICAgICAgICAgIHJvd05hbWVzPVRSVUUpDQoNCmBgYA0KDQojIyBSZXN1bHRzIG92ZXJ2aWV3DQoNCiMjIyMgQWxwaGEgZGl2ZXJzaXR5DQoNCmBgYHtyfQ0KcGNfb2JzZXJ2ZWRbW3NlZ21lbnRdXQ0KcGNfc2hhbm5vbltbc2VnbWVudF1dDQpwY19zaW1wc29uW1tzZWdtZW50XV0NCnBjX3BpZWxvdVtbc2VnbWVudF1dDQpgYGANCg0KUGxvdHMNCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQphbHBoYV9kaXZfcGxvdHNbW3Bhc3RlKHNlZ21lbnQsIkNvdW50cnkiKV1dDQpgYGANCg0KYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTQsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCmFscGhhX2Rpdl9wbG90c1tbcGFzdGUoc2VnbWVudCwiQ3VzdG9tIildXQ0KYGBgDQoNCiMjIyMgQmV0YSBkaXZlcnNpdHkNCg0KKipNYWluIHJlc3VsdHMqKg0KDQpgYGB7cn0NCnBhaXJ3aXNlX2FpdGNoaXNvbl9yYXdbW3Bhc3RlKCJnZW51cyIsIHNlZ21lbnQpXV0NCmBgYA0KDQpQQ0ENCg0KYGBge3IsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTMsIGZpZy5mdWxsd2lkdGg9VFJVRSwgZXZhbD1UUlVFfQ0KcGNhX3Bsb3RzX2xpc3RbW3Bhc3RlKHNlZ21lbnQsImdlbnVzIGN1c3RvbSIpXV0NCmBgYA0KDQoqKlN1cHBsZW1lbnRzKioNCg0KYGBge3J9DQprbml0cjo6a2FibGUoc3VwcGxlbWVudHNfYmV0YVshZ3JlcGwoIlBDb0EiLG5hbWVzKHN1cHBsZW1lbnRzX2JldGEpKV0sDQogICAgICAgICAgICAgZGlnaXRzID0gMywNCiAgICAgICAgICAgICBjYXB0aW9uID0gIlN1cHBsZW1lbnRhcnkgUEVSTUFOT1ZBIHJlc3VsdHMiKQ0KYGBgDQoNClBDQQ0KDQpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NywgZmlnLmZ1bGx3aWR0aD1UUlVFLCBldmFsPVRSVUV9DQpwbG90X2xpc3QgPC0gc3VwcGxlbWVudHNfYmV0YVtncmVwbCgiUENvQSIsbmFtZXMoc3VwcGxlbWVudHNfYmV0YSkpICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKHNlZ21lbnQsbmFtZXMoc3VwcGxlbWVudHNfYmV0YSkpXQ0KDQpnZ2FycmFuZ2UocGxvdGxpc3QgPSBwbG90X2xpc3QsDQogICAgICAgICAgbGFiZWxzPW5hbWVzKHBsb3RfbGlzdCksDQogICAgICAgICAgZm9udC5sYWJlbCA9IGxpc3Qoc2l6ZT01LGZhY2U9InBsYWluIiksDQogICAgICAgICAgbmNvbD0yLG5yb3c9MykNCmBgYA0KDQojIyMjIFVuaXZhcmlhdGUgYW5hbHlzaXMNCg0KKipOdW1iZXIgb2Ygc2lnbmlmaWNhbnQgdGF4YSoqDQoNCmBgYHtyfQ0Ka25pdHI6OmthYmxlKGNiaW5kKGFzLmRhdGEuZnJhbWUobGFwcGx5KGxpc3RfaW50ZXJzZWN0aW9ucyxucm93KSksDQogICAgICBhcy5kYXRhLmZyYW1lKGxhcHBseShycHNjX2VmZmVjdCxucm93KSkpICU+JSB0KCkgJT4lIA0KICBgY29sbmFtZXM8LWAoIkNvdW50IikgJT4lIA0KICBgcm93bmFtZXM8LWAoYyhuYW1lcyhsaXN0X2ludGVyc2VjdGlvbnMpLCJyUFNDIGVmZmVjdCBBU1YiLCJyUFNDIGVmZmVjdCBHZW51cyIsInJQU0MgZWZmZWN0IFBoeWx1bSIpKSxjYXB0aW9uPSJOdW1iZXIgb2Ygc2lnbmlmaWNhbnQgdGF4YSIpDQpgYGANCg0KKipDb3VudHMqKg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiMgdW5pdmFyX2xpc3QgPC0gdW5pdmFyaWF0ZV9zdGF0aXN0aWNzKGxpc3RfaW50ZXJzZWN0aW9ucywNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBzY19lZmZlY3QsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbGV1bV9nZW51c19hc3ZfdGF4YV90YWIpDQojIA0KIyB1bml2YXJfZGYgPC0gdW5pdmFyX2xpc3RbWzFdXQ0KIyB3YiA8LSB1bml2YXJfbGlzdFtbMl1dDQojIA0KIyAjIHNhdmUgdGhlIHJlc3VsdHMNCiMgc2F2ZVdvcmtib29rKHdiLCJyZXN1bHRzL1ExL0RBQV9maW5hbF90ZXJtaW5hbF9pbGV1bS54bHN4Iiwgb3ZlcndyaXRlID0gVFJVRSkNCiMgDQojICMgc2VlIHRoZSByZXN1bHRzDQojIHVuaXZhcl9kZg0KYGBgDQoNCiMjIyMgTWFjaGluZSBsZWFybmluZw0KDQoqKk1haW4gbW9kZWxzKioNCg0KU3VtbWFyeQ0KDQpgYGB7cn0NCmtuaXRyOjprYWJsZShtb2RlbHNfc3VtbV9kZl9jb2xvbiAlPiUgZHBseXI6OnNlbGVjdCgNCiJhbHBoYSIsImxhbWJkYSIsDQoiYXVjX29wdGltaXNtX2NvcnJlY3RlZCIsDQoiYXVjX29wdGltaXNtX2NvcnJlY3RlZF9DSUwiLA0KImF1Y19vcHRpbWlzbV9jb3JyZWN0ZWRfQ0lVIiksDQogICAgICAgICAgICAgZGlnaXRzPTMsY2FwdGlvbj0iRWxhc3RpYyBuZXQgcmVzdWx0cyIpDQpgYGANCg0KKipST0MgLSBBU1YgbGV2ZWwqKg0KDQpgYGB7cn0NCnJvY19jdXJ2ZV9hbGxfY3VzdG9tKHJvY19jc1tjKDk6MTIpXSwgDQogICAgICAgICAgICAgICAgICAgICBRPSJRMiIsDQogICAgICAgICAgICAgICAgICAgICBtb2RlbF9uYW1lPSJlbmV0X21vZGVsIikNCmBgYA0KDQoqKlJPQyAtIEdlbnVzIGxldmVsKioNCg0KYGBge3J9DQpyb2NfY3VydmVfYWxsX2N1c3RvbShyb2NfY3NbYygxMzoxNildLFE9IlEyIiwNCiAgICAgICAgICAgICAgICAgICAgIG1vZGVsX25hbWU9ImVuZXRfbW9kZWwiKQ0KYGBgDQoNCioqU3VwcGxlbWVudGFyeSBtb2RlbHMqKg0KDQpTdW1tYXJ5DQoNCmBgYHtyfQ0KIyBCdWlsZCBmaW5hbCBkYXRhZnJhbWUNCm1vZGVsc19saXN0W1siZW5ldF9tb2RlbCJdXSA8LSByYmluZChtb2RlbHNfc3VtbV9kZl9pbGV1bSxtb2RlbHNfc3VtbV9kZl9jb2xvbikNCmZpbmFsX2RmIDwtIHRpYmJsZShyb3dfbmFtZXMgPSByb3duYW1lcyhtb2RlbHNfbGlzdFtbMV1dKSkNCg0KIyBMb29wIHRocm91Z2ggbW9kZWxzIGFuZCBleHRyYWN0IHJlcXVpcmVkIHZhbHVlcw0KZm9yIChtb2RlbF9uYW1lIGluIG5hbWVzKG1vZGVsc19saXN0KSkgew0KICBtb2RlbF9kZiA8LSBtb2RlbHNfbGlzdFtbbW9kZWxfbmFtZV1dDQogIA0KICAjIENvbWJpbmUgQVVDX29wdGltaXNtX2NvcnJlY3RlZCB3aXRoIGl0cyBDSSB2YWx1ZXMNCiAgZmluYWxfZGZbW21vZGVsX25hbWVdXSA8LSBwYXN0ZTAoDQogICAgcm91bmQobW9kZWxfZGYkYXVjX29wdGltaXNtX2NvcnJlY3RlZCwgMyksIA0KICAgICIgKCIsIHJvdW5kKG1vZGVsX2RmJGF1Y19vcHRpbWlzbV9jb3JyZWN0ZWRfQ0lMLCAzKSwgIjsgIiwgDQogICAgcm91bmQobW9kZWxfZGYkYXVjX29wdGltaXNtX2NvcnJlY3RlZF9DSVUsIDMpLCAiKSINCiAgKQ0KfQ0KDQprbml0cjo6a2FibGUoZmluYWxfZGYsIGNhcHRpb249IkFsbCBtb2RlbHMiKQ0Kd3JpdGUuY3N2KGZpbmFsX2RmLGZpbGU9ZmlsZS5wYXRoKHBhdGgsIkFVQ19hbGxfbW9kZWxzLmNzdiIpLHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNClJPQyAtIEFTVg0KDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTgsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCnJvY3NfbGlzdCA8LSBzdXBwbGVtZW50c19tb2RlbHMkcm9jX2NzDQpyb2NzX2xpc3RbWyJlbmV0X21vZGVsIl1dIDwtIHJvY19jcw0KDQpwbG90X2xpc3QgPC0gbGlzdCgpDQoNCmZvciAobW9kZWxfbmFtZSBpbiBuYW1lcyhyb2NzX2xpc3QpKSB7DQogIHBsb3RfbGlzdFtbbW9kZWxfbmFtZV1dIDwtIHJvY19jdXJ2ZV9hbGxfY3VzdG9tKHJvY3NfbGlzdFtbbW9kZWxfbmFtZV1dW2MoMTo0KV0sDQogICAgICAgICAgICAgICAgICAgICAgIFE9IlEyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgbW9kZWxfbmFtZT1tb2RlbF9uYW1lKQ0KfQ0KDQpnZ2FycmFuZ2UocGxvdGxpc3QgPSBwbG90X2xpc3QsbGFiZWxzID0gbmFtZXMocm9jc19saXN0KSxmb250LmxhYmVsID0gbGlzdChmYWNlPSJwbGFpbiIsc2l6ZT03KSkNCmBgYA0KDQpST0MgLSBnZW51cw0KDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTgsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCnBsb3RfbGlzdCA8LSBsaXN0KCkNCg0KZm9yIChtb2RlbF9uYW1lIGluIG5hbWVzKHJvY3NfbGlzdCkpIHsNCiAgcGxvdF9saXN0W1ttb2RlbF9uYW1lXV0gPC0gcm9jX2N1cnZlX2FsbF9jdXN0b20ocm9jc19saXN0W1ttb2RlbF9uYW1lXV1bYyg1OjgpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiLA0KICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9uYW1lPW1vZGVsX25hbWUpDQp9DQoNCnAgPC0gZ2dhcnJhbmdlKHBsb3RsaXN0ID0gcGxvdF9saXN0LGxhYmVscyA9IG5hbWVzKHJvY3NfbGlzdCksZm9udC5sYWJlbCA9IGxpc3QoZmFjZT0icGxhaW4iLHNpemU9NykpDQpgYGANCg0KYGBge3IscmVzdWx0cz0naGlkZSd9DQpwZGYoIi4uL2ZpZ3VyZXMvUTIvbW9kZWxzX2NvbG9uLnBkZiIsDQogICAgaGVpZ2h0ID0xMCx3aWR0aCA9IDEwKQ0KcA0KZGV2Lm9mZigpDQpgYGANCg0KIyBQYXBlci1yZWFkeSB2aXN1YWxpemF0aW9ucw0KDQojIyBBbHBoYSBkaXZlcnNpdHkNCg0KYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00LCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpwX0EgPC0gYWxwaGFfZGl2X3Bsb3RzJGB0ZXJtaW5hbF9pbGV1bSBDb3VudHJ5YCArDQogIGdndGl0bGUoIlRlcm1pbmFsIGlsZXVtIikrDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41LGZhY2UgPSAiYm9sZCIsc2l6ZSA9IDE1KSkgDQoNCnBfQiA8LSAgYWxwaGFfZGl2X3Bsb3RzJGBjb2xvbiBDb3VudHJ5YCArDQogIGdndGl0bGUoIkNvbG9uIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuNSxmYWNlID0gImJvbGQiLHNpemUgPSAxNSkpIA0KDQpRMl9hbHBoYSA8LSBnZ2FycmFuZ2UocF9BLGdncGxvdCgpICsgdGhlbWVfbWluaW1hbCgpLHBfQixucm93PTEsIG5jb2w9MywNCiAgICAgICAgICAgICAgICAgICAgICB3aWR0aHMgPSBjKDEsMC4xLDEpKQ0KUTJfYWxwaGENCmBgYA0KDQojIyBCZXRhIGRpdmVyc2l0eQ0KDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KcGNhX3RpIDwtIHBjYV9wbG90c19saXN0JGB0ZXJtaW5hbF9pbGV1bSBnZW51cyBjdXN0b21gIA0KcGNhX2NvbG9uIDwtIHBjYV9wbG90c19saXN0JGBjb2xvbiBnZW51cyBjdXN0b21gIA0KDQpnZW51c19RMl9iZXRhIDwtIGdnYXJyYW5nZShwY2FfdGksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoKSArIHRoZW1lX21pbmltYWwoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHBjYV9jb2xvbixuY29sPTMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aHMgPSBjKDEsMC4xLDEpKQ0KZ2VudXNfUTJfYmV0YQ0KYGBgDQoNCioqQWxwaGEgKyBCZXRhIGRpdmVyc2l0eSoqDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9OCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KYWxwaGFfYmV0YSA8LSBnZ2FycmFuZ2UoUTJfYWxwaGEsZ2VudXNfUTJfYmV0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLG5yb3c9MixsYWJlbHMgPSBjKCJBIiwiQiIpKQ0KYWxwaGFfYmV0YQ0KYGBgDQoNCiMjIEVsYXN0aWMgbmV0DQoNCkdlbnVzIGxldmVsDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfQ0KbW9kZWxzX3RvX3Bsb3QgPC0gYygia25uX21vZGVsIiwicmZfbW9kZWwiLCJnYm1fbW9kZWwiLCJlbmV0X21vZGVsIikNCm5hbWVzKG1vZGVsc190b19wbG90KSA8LSBjKCJrTk4iLCJSRiIsIkdCb29zdCIsIkVOZXQiKQ0KDQojIElMRVVNDQpwbG90X2xpc3RfaWxldW0gPC0gbGlzdCgpDQpmb3IgKG1vZGVsX25hbWUgaW4gbW9kZWxzX3RvX3Bsb3QpIHsNCiAgcGxvdF9saXN0X2lsZXVtW1ttb2RlbF9uYW1lXV0gPC0gDQogICAgcm9jX2N1cnZlX2FsbF9jdXN0b20ocm9jc19saXN0W1ttb2RlbF9uYW1lXV1bYyg1OjgpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgUT0iUTIiLA0KICAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9uYW1lPW1vZGVsX25hbWUsbGVnZW5kID0gRkFMU0UpICsgDQogICAgZ2d0aXRsZShuYW1lcyhtb2RlbHNfdG9fcGxvdClbd2hpY2gobW9kZWxfbmFtZT09bW9kZWxzX3RvX3Bsb3QpXSkgKyANCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsc2l6ZSA9IDgpKSANCn0NCg0Kcm9jX2N1cnZlX3RpIDwtIGdnYXJyYW5nZShwbG90bGlzdCA9IHBsb3RfbGlzdF9pbGV1bSkNCg0KIyBDT0xPTg0KDQpwbG90X2xpc3RfY29sb24gPC0gbGlzdCgpDQpmb3IgKG1vZGVsX25hbWUgaW4gbW9kZWxzX3RvX3Bsb3QpIHsNCiAgcGxvdF9saXN0X2NvbG9uW1ttb2RlbF9uYW1lXV0gPC0gDQogICAgcm9jX2N1cnZlX2FsbF9jdXN0b20ocm9jc19saXN0W1ttb2RlbF9uYW1lXV1bYygxMzoxNildLA0KICAgICAgICAgICAgICAgICAgICAgICBRPSJRMiIsDQogICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX25hbWU9bW9kZWxfbmFtZSxsZWdlbmQgPSBGQUxTRSkgKyANCiAgICBnZ3RpdGxlKG5hbWVzKG1vZGVsc190b19wbG90KVt3aGljaChtb2RlbF9uYW1lPT1tb2RlbHNfdG9fcGxvdCldKSArIA0KICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIixzaXplID0gOCkpICANCn0NCg0Kcm9jX2N1cnZlX2NvbG9uIDwtIGdnYXJyYW5nZShwbG90bGlzdCA9IHBsb3RfbGlzdF9jb2xvbikNCg0KDQpyb2NfY3VydmVfcGxvdCA8LSBnZ2FycmFuZ2Uocm9jX2N1cnZlX3RpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdncGxvdCgpICsgdGhlbWVfbWluaW1hbCgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvY19jdXJ2ZV9jb2xvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoKSArIHRoZW1lX21pbmltYWwoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sPTQsIHdpZHRocyA9IGMoMSwwLjEsMSwwLjEpKQ0Kcm9jX2N1cnZlX3Bsb3QNCg0KYGBgDQoNCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTIsIGZpZy5mdWxsd2lkdGg9VFJVRX0NCmFscGhhX2JldGFfZWxhc3RpYyA8LSBnZ2FycmFuZ2UoUTJfYWxwaGEsZ2VudXNfUTJfYmV0YSxyb2NfY3VydmVfcGxvdCwNCiAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLG5yb3c9MyxsYWJlbHMgPSBMRVRURVJTLGhlaWdodHMgPSBjKDEsMSwxLjIpKQ0KYWxwaGFfYmV0YV9lbGFzdGljDQpgYGANCg0KYGBge3IscmVzdWx0cz0naGlkZSd9DQpwZGYoIi4uL2ZpZ3VyZXMvUTIvRklHVVJFNC5wZGYiLHBhcGVyID0gImE0IixoZWlnaHQgPSAxMCx3aWR0aCA9IDEwKQ0KYWxwaGFfYmV0YV9lbGFzdGljDQpkZXYub2ZmKCkNCmBgYA0KDQojIyBEb3QgaGVhdG1hcCAtIERBQQ0KDQpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTEzLCBmaWcuZnVsbHdpZHRoPVRSVUV9DQpwX2lsZXVtIDwtIGRvdF9oZWF0bWFwX2lsZXVtICsgDQogIGdndGl0bGUoIlRlcm1pbmFsIGlsZXVtIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuNSxmYWNlID0gImJvbGQiLHNpemUgPSAxNSksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KDQpwX2NvbG9uIDwtIGRvdF9oZWF0bWFwX2NvbG9uICArDQogIGdndGl0bGUoIkNvbG9uIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuNSxmYWNlID0gImJvbGQiLHNpemUgPSAxNSksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KaGVhdG1hcF9wbG90IDwtIGdnYXJyYW5nZShwX2lsZXVtLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwX2NvbG9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMikNCmhlYXRtYXBfcGxvdA0KYGBgDQoNCmBgYHtyLHJlc3VsdHM9J2hpZGUnfQ0KcGRmKCIuLi9maWd1cmVzL1EyL0ZJR1VSRTUucGRmIiwNCiAgICBoZWlnaHQgPTEwLHdpZHRoID0gOCxwYXBlcj0iYTQiKQ0KaGVhdG1hcF9wbG90DQpkZXYub2ZmKCkNCmBgYA0KDQojIFNlc3Npb24gaW5mbw0KDQpgYGB7cn0NCnNlc3Npb25JbmZvKCkNCmBgYA0KDQoNCjwhLS0gIyBQYXBlci1yZWFkeSB2aXN1YWxpemF0aW9ucyAtLT4NCg0KPCEtLSAjIyBBbHBoYSBkaXZlcnNpdHkgLS0+DQoNCjwhLS0gKipBbHBoYSBkaXZlcnNpdHkqKiAtLT4NCg0KPCEtLSBgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTQsIGZpZy5mdWxsd2lkdGg9VFJVRX0gLS0+DQo8IS0tIHBfQSA8LSBhbHBoYV9kaXZfcGxvdHMkYElsZXVtIEN1c3RvbWAgKyAgLS0+DQo8IS0tICAgZ2d0aXRsZSgiVGVybWluYWwgaWxldW0iKSsgIC0tPg0KPCEtLSAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41LGZhY2UgPSAiYm9sZCIsc2l6ZSA9IDE1KSkgLS0+DQoNCjwhLS0gcF9CIDwtICBhbHBoYV9kaXZfcGxvdHMkYENvbG9uIEN1c3RvbWAgKyAgLS0+DQo8IS0tICAgZ2d0aXRsZSgiQ29sb24iKSArICAtLT4NCjwhLS0gICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuNSxmYWNlID0gImJvbGQiLHNpemUgPSAxNSkpIC0tPg0KDQo8IS0tIFExX2FscGhhIDwtIGdnYXJyYW5nZShwX0EsZ2dwbG90KCkgKyB0aGVtZV9taW5pbWFsKCkscF9CLG5yb3c9MSwgbmNvbD0zLCAtLT4NCjwhLS0gICAgICAgICAgICAgICAgICAgICAgIHdpZHRocyA9IGMoMSwwLjEsMSkpIC0tPg0KPCEtLSBRMV9hbHBoYSAtLT4NCjwhLS0gYGBgIC0tPg0KDQo8IS0tICMjIEJldGEgZGl2ZXJzaXR5IC0tPg0KDQo8IS0tIEFTViBsZXZlbCAtLT4NCg0KPCEtLSBgYGB7cn0gLS0+DQoNCjwhLS0gYGBgIC0tPg0KDQo8IS0tIEdlbnVzIGxldmVsIC0tPg0KDQo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfSAtLT4NCjwhLS0gcGNhX3RpIDwtIHBjYV9wbG90c19saXN0JGBRMSBJbGV1bSBHZW51cyBjdXN0b21gICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAtLT4NCjwhLS0gcGNhX2NvbG9uIDwtIHBjYV9wbG90c19saXN0JGBRMSBDb2xvbiBHZW51cyBjdXN0b21gICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAtLT4NCg0KPCEtLSBnZW51c19RMV9iZXRhIDwtIGdnYXJyYW5nZShwY2FfdGksIC0tPg0KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoKSArIHRoZW1lX21pbmltYWwoKSwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBjYV9jb2xvbixuY29sPTMsIC0tPg0KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aHMgPSBjKDEsMC4xLDEpKSAtLT4NCjwhLS0gZ2VudXNfUTFfYmV0YSAtLT4NCjwhLS0gYGBgIC0tPg0KDQo8IS0tICoqQWxwaGEgKyBCZXRhIGRpdmVyc2l0eSoqIC0tPg0KDQo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9OCwgZmlnLmZ1bGx3aWR0aD1UUlVFfSAtLT4NCjwhLS0gYWxwaGFfYmV0YSA8LSBnZ2FycmFuZ2UoUTFfYWxwaGEsZ2VudXNfUTFfYmV0YSwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLG5yb3c9MixsYWJlbHMgPSBjKCJBIiwiQiIpKSAtLT4NCjwhLS0gYWxwaGFfYmV0YSAtLT4NCjwhLS0gYGBgIC0tPg0KDQo8IS0tICMjIEVsYXN0aWMgbmV0IC0tPg0KDQo8IS0tIEFTViBsZXZlbCAtLT4NCg0KPCEtLSBgYGB7cn0gLS0+DQoNCjwhLS0gYGBgIC0tPg0KDQo8IS0tIEdlbnVzIGxldmVsIC0tPg0KDQo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NCwgZmlnLmZ1bGx3aWR0aD1UUlVFfSAtLT4NCjwhLS0gcm9jX2NzX3RpIDwtIHJvY19jc1s0OjZdIC0tPg0KPCEtLSByb2NfY3NfY29sb24gPC0gcm9jX2NzWzEwOjEyXSAtLT4NCg0KPCEtLSByb2NfY3VydmVfdGkgPC0gcm9jX2N1cnZlX2FsbF9jdXN0b20ocm9jX2NzX3RpLCBRID0gIlEyIixsZWdlbmQgPSBGQUxTRSkgLS0+DQoNCjwhLS0gcm9jX2N1cnZlX2NvbG9uIDwtIHJvY19jdXJ2ZV9hbGxfY3VzdG9tKHJvY19jc19jb2xvbiwgUT0iUTIiLGxlZ2VuZD1GQUxTRSkgIC0tPg0KDQo8IS0tIHJvY19jdXJ2ZV9wbG90IDwtIGdnYXJyYW5nZShnZ3Bsb3QoKSArIHRoZW1lX21pbmltYWwoKSwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb2NfY3VydmVfdGksIC0tPg0KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkgKyB0aGVtZV9taW5pbWFsKCksIC0tPg0KPCEtLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9jX2N1cnZlX2NvbG9uLCAtLT4NCjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdncGxvdCgpICsgdGhlbWVfbWluaW1hbCgpLCAtLT4NCjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2w9NSwgd2lkdGhzID0gYygwLjEsMSwwLjIsMSwwLjEpLCAtLT4NCjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCIiLCJBIiwiIiwiQiIsIiIpKSAtLT4NCg0KPCEtLSByb2NfY3VydmVfcGxvdCA8LSBnZ2FycmFuZ2Uocm9jX2N1cnZlX3RpLCAtLT4NCjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdncGxvdCgpICsgdGhlbWVfbWluaW1hbCgpLCAtLT4NCjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvY19jdXJ2ZV9jb2xvbiwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoKSArIHRoZW1lX21pbmltYWwoKSwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sPTQsIHdpZHRocyA9IGMoMSwwLjEsMSwwLjEpKSAtLT4NCjwhLS0gcm9jX2N1cnZlX3Bsb3QgLS0+DQoNCjwhLS0gYGBgIC0tPg0KDQo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTIsIGZpZy5mdWxsd2lkdGg9VFJVRX0gLS0+DQo8IS0tIGFscGhhX2JldGFfZWxhc3RpYyA8LSBnZ2FycmFuZ2UoUTFfYWxwaGEsZ2VudXNfUTFfYmV0YSxyb2NfY3VydmVfcGxvdCwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLG5yb3c9MyxsYWJlbHMgPSBMRVRURVJTLGhlaWdodHMgPSBjKDEsMSwxKSkgLS0+DQo8IS0tIGFscGhhX2JldGFfZWxhc3RpYyAtLT4NCjwhLS0gYGBgIC0tPg0KDQo8IS0tICMjIERvdCBoZWF0bWFwIC0gREFBIC0tPg0KDQo8IS0tIEFTViBsZXZlbCAtLT4NCg0KPCEtLSBgYGB7cn0gLS0+DQoNCjwhLS0gYGBgIC0tPg0KDQo8IS0tIEdlbnVzIGxldmVsIC0tPg0KDQo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTMsIGZpZy5mdWxsd2lkdGg9VFJVRX0gLS0+DQo8IS0tIGxpc3RfZm9yX2hlYXRtYXBfaWxldW0gPC0gYyhsaXN0X2ludGVyc2VjdGlvbnNbYyg0LDUsNildKSAtLT4NCjwhLS0gbGlzdF9mb3JfaGVhdG1hcF9jb2xvbiA8LSBjKGxpc3RfaW50ZXJzZWN0aW9uc1tjKDEwLDExLDEyKV0pIC0tPg0KDQo8IS0tIG5hbWVzKGxpc3RfZm9yX2hlYXRtYXBfY29sb24pIDwtIGdzdWIoIkdlbnVzIiwiIixnc3ViKCJjb2xvbiIsIiIsbmFtZXMobGlzdF9mb3JfaGVhdG1hcF9jb2xvbikpKSAtLT4NCjwhLS0gbmFtZXMobGlzdF9mb3JfaGVhdG1hcF9pbGV1bSkgPC0gZ3N1YigiR2VudXMiLCIiLGdzdWIoIklsZXVtIiwiIixuYW1lcyhsaXN0X2Zvcl9oZWF0bWFwX2lsZXVtKSkpIC0tPg0KDQo8IS0tIHBfaWxldW0gPC0gZG90X2hlYXRtYXBfbGluZGEobGlzdF9mb3JfaGVhdG1hcF9pbGV1bSwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWxldW1fdGF4YV90YWIpICsgeGxhYigiIikgKyB5bGFiKCIiKSArICAtLT4NCjwhLS0gICBnZ3RpdGxlKCJUZXJtaW5hbCBpbGV1bSIpICsgIC0tPg0KPCEtLSAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3Q9MC41LGZhY2UgPSAiYm9sZCIsc2l6ZSA9IDE1KSwgLS0+DQo8IS0tICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAtLT4NCg0KDQo8IS0tIHBfY29sb24gPC0gZG90X2hlYXRtYXBfbGluZGEobGlzdF9mb3JfaGVhdG1hcF9jb2xvbiwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb25fdGF4YV90YWIpICsgeGxhYigiIikgKyB5bGFiKCIiKSArIC0tPg0KPCEtLSAgIGdndGl0bGUoIkNvbG9uIikgKyAgLS0+DQo8IS0tICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUsZmFjZSA9ICJib2xkIixzaXplID0gMTUpLCAtLT4NCjwhLS0gICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIC0tPg0KDQo8IS0tIGhlYXRtYXBfcGxvdCA8LSBnZ2FycmFuZ2UocF9pbGV1bSwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgcF9jb2xvbiwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDIpICAtLT4NCjwhLS0gaGVhdG1hcF9wbG90IC0tPg0KPCEtLSBgYGAgLS0+DQoNCjwhLS0gIyMgQWxsIHRvZ2V0aGVyIC0tPg0KDQo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTgsIGZpZy5oZWlnaHQ9MTAsIGZpZy5mdWxsd2lkdGg9VFJVRX0gLS0+DQoNCjwhLS0gcTFfcGxvdCA8LSBnZ2FycmFuZ2UoYWxwaGFfYmV0YV9lbGFzdGljLCAtLT4NCjwhLS0gICAgICAgICAgICAgICAgICAgICAgZ2dwbG90KCkrIHRoZW1lX21pbmltYWwoKSwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgIGhlYXRtYXBfcGxvdCwgLS0+DQo8IS0tICAgICAgICAgICAgICAgICAgICAgICBnZ3Bsb3QoKSsgdGhlbWVfbWluaW1hbCgpLCAtLT4NCjwhLS0gICAgICAgICAgICAgICAgICAgICAgbmNvbD00LGxhYmVscz1jKCIiLCIiLCAiRCIsIiIpLHdpZHRocyA9IGMoMSwwLjIsMC44LDAuMTUpKSAtLT4NCjwhLS0gcTFfcGxvdCAtLT4NCjwhLS0gYGBgIC0tPg0KDQo8IS0tIGBgYHtyLCBldmFsPUZBTFNFfSAtLT4NCjwhLS0gcGRmKCJjbGFub2svb2JyYXpreS9xMS9RMV9wbG90X25ld2FscGhhLnBkZiIsaGVpZ2h0ID0gMTAsd2lkdGggPSAxNykgLS0+DQo8IS0tIHExX3Bsb3QgLS0+DQo8IS0tIGRldi5vZmYoKSAtLT4NCjwhLS0gYGBgIC0tPg0KDQo8IS0tICMgU2Vzc2lvbiBpbmZvIC0tPg0KDQo8IS0tIGBgYHtyfSAtLT4NCjwhLS0gc2Vzc2lvbkluZm8oKSAtLT4NCjwhLS0gYGBgIC0tPg0K